js 对象原型和原型链
JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。
准确地说,这些属性和方法定义在Object的构造器函数(constructor functions)之上的prototype
属性上,而非对象实例本身。
function P(name) {
this.name = name;
this.say = function(){
console.log(\`this is my name -- ${this.name}\`);
}
}
var p1 = new P('abc')
p1.\_\_proto\_\_ == P.prototype; //true
MDN文档上说了 __proto__ 已经废弃了,为了更好的支持,建议只使用 [Object.getPrototypeOf()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf)
。
Object.getPrototypeOf(new P) == p1.\_\_proto\_\_; //true
Object.getPrototypeOf(new P) == P.prototype; //true
注意:
__proto__
和constructor
属性是对象所独有的;prototype
属性是函数所独有的。
1、__proto__ 指向父原型对象,
它的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(可以理解为父对象)里找,
如果父对象也不存在这个属性,则继续往父对象的__proto__属性所指向的那个对象(可以理解为爷爷对象)里找,
如果还没找到,则继续往上找…直到原型链顶端如果还没找到,则继续往上找…直到原型链顶端null(可以理解为原始人。。。),
再往上找就相当于在null上取值,会报错(可以理解为,再往上就已经不是“人”的范畴了,找不到了,到此结束,null为原型链的终点),
由以上这种通过__proto__属性来连接对象直到null的一条链即为我们所谓的原型链。
2、prototype 从函数指向对象,它是函数独有的属性
prototype 指的是函数的原型对象,也就是这个函数创建实例时的原型对象。
它的作用就是让函数实例化的对象们都可以找到公用的属性和方法。
任何函数创建时,都会默认同时创建该函数的prototype对象。
3、constructor 从对象指向函数,它是对象独有的属性
constructor 指的是对象的构造函数,每个对象都有构造函数。
所有的对象和函数最终都是由 Function 构造函数得来的,所以 constructor 的终点是 Function。
继承方法:
1、call、apply、bind
obj.call(thisObj, arg1, arg2, ...);
obj.apply(thisObj, [arg1, arg2, ...]);
obj.bind(thisObj, arg1, arg2, ...)();
把obj的 this 绑定到 thisObj 上,这时候thisObj具备了(或者说继承了)obj的属性和方法,然后在thisObj的执行环境里面执行obj的属性和方法,绑定后会立即执行函数(bind需要手动执行);