原型
-
定义函数时,解析会为它添加一个
prototype
属性,默认总是指向一个对象,即原型对象。- 如果把函数作为普通函数调用,
prototype
不会有任何作用; - 如果以构造函数的形式调用,它创建的对象中都会有一个隐含的属性
__proto__
,指向构造函数的原型对象;
- 如果把函数作为普通函数调用,
-
prototype
又称为显式原型,__proto__
又称为隐式原型。 -
原型对象中一定包含属性
constructor
,除了Object
的原型对象之外,又会添加属性__proto__
-
constructor
指向(构造)函数本身function Person() {} Person.prototype.constructor === Person // true
-
__proto__
指向自己父类原型对象,默认指向JavaScript
的顶层对象Object
的原型对象。Person.prototype.__proto__ === Object.prototype // true
-
-
Object
和Function
也是构造函数-
Object
处在JavaScript
中的顶层,所以它的原型对象没有__proto__
属性,其中定义了一些基本的方法,诸如hasOwnProperty、isPrototypeOf、toString...
,而这些方法是供对象使用的,对象通过原型链(__proto__
)找到这些方法; -
Function
的原型比较特殊,它不是一个对象,而是指向一个函数体,它上面除了具有constructor
和__proto__
这两个属性之外,还定义了函数的一些基本属性和方法,诸如apply、arguments、bind、call、caller、length、name...
Function.prototype // ƒ () { [native code] } Function.prototype.constructor === Function // true Function.prototype.__proto__ === Object.prototype // true
-
-
JS
的函数也是一种对象,所有函数(包括Object
和Function
)都有constructor
和__proto__
这两个属性。-
constructor
指向的正是Function
Person.constructor = Object.constructor = Function.constructor = Function
-
__proto__
则指向Function
的原型,所以函数都可以通过原型链访问Function
的原型上定义的属性和方法。Person.__proto__ = Object.__proto__ = Function.__proto__ = Function.prototype
-

原型链
原型链体现在 __proto__
属性的作用上。
当访问一个对象的属性(或方法)时,如果该对象内部不存在这个属性,那么就会去它的__proto__
属性所指向的那个对象(父对象)里找,直到__proto__
属性的终点Object.prototype.__proto__ = null
,再往上查找会报错。通过__proto__
属性将连接起来的这条链路就是所谓的原型链。
总结
-
__proto__
和constructor
属性是对象所独有的; -
prototype
属性是函数所独有的,因为函数也是一种对象,所以函数也拥有__proto__
和constructor
属性; -
prototype
属性的作用就是让该函数所实例化的对象们都可以找到公用的属性和方法,即f1.__proto__ === Foo.prototype
。 -
constructor
属性指向对象的构造函数,所有函数(对象)最终的构造函数都指向Function
。 -
prop in obj
:检查对象obj
是否有属性prop
,如果对象中没有,会检查原型链; -
obj.hasOwnProperty(prop)
:只检查对象自身中是否有某个属性; -
A instanceof B
的判断标准:如果B
的显示原型在A
的原型链上,则返回true
。
Function instanceof Object // true
Object instanceof Function // true
网友评论