# 原型与原型链
继承是为了方便代码的复用(数值、函数方法、属性),JS 采用了原型方案来实现继承,原型就是继承的实现方式之一!
原型与原型链对于一个将走进高级 web 前端来讲,是一个门槛。由于概念性比较多。
原型:指的是 JS 函数都有一个叫 prototype
的对象属性,用来实现构造函数的实例继承。也就是构造函数的原型,可以为构造函数绑定一些方法和属性,用给实例继承
__proto__
:每个对象都有一个叫 __proto__
的内在属性,原型链的对象正是依靠此属性连接
原型链:作为一个对象,当访问其中一个属性或方法时,如果当前对象找不到,JavaScript 引擎将会访问这个对象 __proto__
属性所指向上一个对象上,一层一层往上找,直至这个链表结束
function A() {} // function 声明
const a = new A(); // A 即为构造函数、a 实例化
console.log(typeof a); // "object"
console.log(typeof A); // "function"
console.log(a.prototype); // undefined
console.log(a.__proto__); // 指向构造函数 A constructor
console.log(a.__proto__ === A.prototype); // true
console.log(a.__proto__.constructor === A); // true
console.log(a.constructor === A); // true
# 概念定义
prototype
/*例子demo*/
function Animal(name) {
this.name = name;
this.getName = function() {
return this.name;
};
}
function Cat(name, age) {
Animal.call(this, name);
this.age = age || 1;
this.meow = function() {
return "name:" + this.getName() + "\n" + "age:" + this.age;
};
}
const cat = new Cat("Lily", 2);
console.log(cat.meow());
/**
*@desc 注释解析 demo
*/
// 声明一个函数Animal,这里一定要入参name 值,否则函数里面的this 是一个undefined
function Animal(name) {
this.name = name; // 实例会有一个name 属性和 一个getName的方法,会返回name的值
this.getName = function() {
return this.name;
};
//此时的this > Cat={name:Lily,age:2,getName:function(){},meow:function(){}}
}
// 声明一只猫
function Cat(name, age) {
//通过call改变上下文的方法,去入参Lily 去调用 Animal方法,此时入参的this 是什么?!!!
// name 这里传递给函数Animal,而使用function 声明的函数,都是函数对象,它就是一个object
Animal.call(this, name);
this.age = age || 1;
this.meow = function() {
return "name:" + this.getName() + "\n" + "age:" + this.age;
};
}
const cat = new Cat("Lily", 2);
console.log(cat.meow());
__proto__
constructor
/*定义一个函数test*/
function test() {
console.log("I am test");
}
test.children = "Leo";
/* 这时候如何取出Leo 的值?*/
test.children;
/* 假如很多呢?*/
test.prototype.constructor.children;
# 构造函数
# JS 原型继承的几种方法
# 闭包(closure)函数
定义:指 有权访问另外一个函数作用域中变量的函数!
- 闭包只能取到包含函数中任何变量的最后一个的值
//闭包,不符合预期
function test() {
var arr = [];
for (var i = 0; i < 10; i++) {
arr[i] = function() {
console.log(i);
};
}
return arr;
}
var myArr = test();
for (var j = 0; j < 10; j++) {
myArr[j]();
}
// 立即执行函数解决闭包
function test() {
var arr = [];
for (var i = 0; i < 10; i++) {
(function(j) {
arr[j] = function() {
console.log(j);
};
})(i);
}
return arr;
}
var myArr = test();
for (var j = 0; j < 10; j++) {
myArr[j]();
}
闭包的特点
- 闭包,是指有权访问另外一个函数作用域中变量的函数。a 函数内,创建一个 b 函数。
- 指函数内部保留变量,被另外一个函数访问
- 有权访问另外一个函数作用域内变量的函数都是闭包。
- 变量被引用着,就不会被回收
- 技术上,所有 js 函数都是闭包,都是对象,关联到作用域链
- 造成原始作用域链不释放,造成内存泄露
闭包的场景
- 闭包替代全局变量
- 函数外或其他函数中访问某一个函数内部参数
- 函数执行之前,为要执行后一个函数提供具体的参数
- 为函数执行之前提供质优在函数执行或引用时才能知道的具体参数
- 为节点循环绑定 click 事件,在事件函数中使用档次循环的值或节点,而不是最后一次循环的值或节点
- 暂停执行(怎么理解)
- 包装相关功能
function a() {
function b() {}
}
//1、demo1
function a() {
var n = 0;
function b() {
n++;
console.info(n);
}
b();
b();
}
a(); // 1 //2
//2、demo2
function f() {
var n = 0;
this.inc = function() {
n++;
console.info(n);
};
}
var c = new a();
c.inc(); //1
c.inc(); //2
//3、demo3
function f() {
var n = 0;
function inc() {
n++;
console.info(n);
}
return inc;
}
var c = new f();
c(); //1
c(); //2
- 如何避免闭包?
- 闭包的应用场景?
Hello world !以下为技术题目: