深入理解js的原型

139 阅读2分钟

一、prototype

prototype是一个显示原型属性,当我们声明一个函数时,这个属性就自动创建了。


constructor对应着构造函数,也就是Foo。一旦我们重写了原型,这个属性就不存在了,这里有疑问。

function Foo(){

}
Foo.prototype = {
    a : 1
};
console.log(Foo.prototype);
function Person(){
}
Person.prototype = {
    name:'kimi'
};



___proto__ : 这是每个对象都会有的隐式原型属性,指向了创建该对象的原型。其实这个属性指向了[[prototype]],但是[[prototype]]是内部属性,我们返问不到,所以用__proto__来访问。

实例对象的__proto__是如何产生的?

当我们使用new操作符时,生成的实例对象拥有了__prototype__;

function Foo() {}
// 这个函数是 Function 的实例对象
// function 就是一个语法糖
// 内部调用了 new Function(...)

new的过程

function Person(name){
    this.name = name;
};

function create(o,name) {
    // 创建一个空的对象
    let obj = new Object();
    // 获得构造函数
    let Con = [].shift.call(arguments);
    console.log(Con);
    // 链接到原型
    obj.__proto__ = Con.prototype;
    // 绑定 this,执行构造函数
    let result = Con.apply(obj,arguments);
    // 确保 new 出来的是个对象
    console.log(result);  //undefined  因为apply函数的内部result = context.fn()没有返回值。
    return typeof result === 'object' ? result : obj
}

console.log(create(Person,'kimi'));

Function.proto === Function.prototype

首先引擎创建了 Object.prototype ,然后创建了 Function.prototype ,并且通过 __proto__ 将两者联系了起来。

有了 Function.prototype 以后才有了 function Function() ,其他所有的构造函数都可以通过原型链找到 Function.prototype ,并且 function Function() 本质也是一个函数,为了不产生混乱就将 function Function()__proto__ 联系到了 Function.prototype 上。

总结

  • Object 是所有对象的爸爸,所有对象都可以通过 __proto__.constructor 找到它
  • Function 是所有函数的爸爸,所有函数都可以通过 __proto__.constructor 找到它
  • Function.prototypeObject.prototype 是两个特殊的对象,他们由引擎来创建
  • 除了以上两个特殊对象,其他对象都是通过构造器 new 出来的
  • 函数的 prototype 是一个对象,也就是原型
  • 对象的 __proto__ 指向原型, __proto__ 将对象和原型连接起来组成了原型链