错误之处,欢迎指正。
1. 原型和原型链
- 所有函数都有
prototype这个属性,这个属性指向该函数的原型。原型是一个对象格式。 - 所有对象都有
__proto__这个属性,这个属性指向该对象的构造函数的原型。注意:使用__proto__是不被推荐的一种方式,推荐使用Object上的静态方法Object.getPrototypeOf(obj)来获取该对象的构造函数的原型。 - 函数也是对象,函数也具有
__proto__这个属性,指向构造函数Function的原型。 -
Function可以理解为是javascript帮我们写好的,Function.__proto__ === Function.prototype Object.prototype.__proto__ === null- 当调用一个对象/函数上的属性时,先去自身找,如果自身没有,去
__proto__上找(构造该对象的构造函数的原型,xxx.__proto__),如果构造函数的原型上没有,去该构造函数的原型的__proto__上找(构造函数的原型的构造函数的原型xxx.__proto__.__proto__),一直到找到,或者返回null为止。
2. 例题
const F = function () {}; //构造函数F
const obj = new F(); //构造函数F构造的对象obj
Object.prototype.a = 'chris';
Function.prototype.b = '22';
console.log(obj.a);
console.log(obj.b);
console.log(F.a);
console.log(F.b);
- 首先看
obj.a,obj是一个对象,它自身没有a这个属性,那么去它的构造函数原型(obj.__proto__)上寻找,它的构造函数是F,那么该构造函数的原型是F.prototype,然而依然没有,那么继续找F.prototype.__proto__,F.prototype是一个对象,它的构造函数是Object,因此,找到了Object.prototype,所以obj.a输出的是chris。 - 再看
obj.b,这里就不再赘述了,从Object.prototype开始说,在这里依然没找到b,那么继续向上找Object.prototype.__proto__,此时返回了null,所以obj.b输出的是undefined。 -
F.a和F.b,F是一个函数,它自身没有a和b这两个属性,那么去它的构造函数原型(F.__proto__)上寻找,它的构造函数是Function,那么该构造函数的原型是Function.prototype,然而依然没有a,但是此时找到了b,所以F.b输出的是22,那么继续找Function.prototype.__proto__,Function.prototype是一个对象,它的构造函数是Object,因此,找到了Object.prototype,所以F.a输出的是chris。
3. 和原型相关的关键字和属性
- instanceof
const obj = {};
function a() {};
console.log(obj instanceof Object); //true
console.log(obj instanceof Function); //false
console.log(a instanceof Object); //true
console.log(a instanceof Function); //true
简单来说,可以把instanceof当做“是”,例如上述:
“obj是个对象”,就正确;“obj是个方法”,很明显这是不正确的。实际上,instanceof是判断obj的原型链上是否有Object的原型。
isPrototypeOf
const obj = {};
function a() {}
console.log(Object.prototype.isPrototypeOf(obj)); //true
console.log(Function.prototype.isPrototypeOf(obj)); //false
console.log(Object.prototype.isPrototypeOf(a)); //true
console.log(Function.prototype.isPrototypeOf(a)); //true
通过isPrototypeOf来判断obj的原型链上是否有object的原型。
hasOwnProperty
Object.prototype.age = '22';
const obj = {
name: 'chris'
}
console.log(obj.name); //chris
console.log(obj.age); //22
console.log(obj.hasOwnProperty('name')); //true
console.log(obj.hasOwnProperty('age')); //false
判断是自身的属性,还是原型上的属性。
Object.create()
Object.prototype.name = 'chris';
const obj = Object.create(Object.prototype);
console.log(obj.name); //chris
以Object.prototype为obj的隐式原型创建obj。