prototype

原型链

创建对象有几种方法

  • 对象字面量
var o1 = { name: "o1" }; // 对象原型链指向 object,故此归为一类
var o2 = new Object({ name: "o2" });
  • 通过构造函数
var M = function(name) {
  this.name = "o3";
};
var o3 = new M("o3");
  • Object.create
var p = { name: "p" };
var o4 = Object.create(p);

原型、构造函数、实例、原型链

  • 函数才有 prototype,实例对象是没有 prototype 的,函数既是函数也是对象,因此有 proto
M.__proto__ === Function.prototype; // true

instanceof 的原理

  • instanceof 的原理就是判断实例对象的 proto 与构造函数的 prototype 的引用是否相同
  • 只要在原型链上的构造函数,instanceof 都会返回 true
o3 instanceof M; // true
o3.__proto__ === M.prototype; // true
M.prototype.__proto__ === Object.prototype; // true
// 用 constructor 来判断会更严谨
o3.__proto__.constructor === M; // true
o3.__proto__.constructor === Object; // false
function instanceof(left, right) {
    // 获得类型的原型
    let prototype = right.prototype
    // 获得对象的原型
    left = left.__proto__
    // 判断对象的类型是否等于类型的原型
    while (true) {
        if (left === null)
            return false
        if (prototype === left)
            return true
        left = left.__proto__
    }
}

new 运算符

  • 一个新对象被创建。它继承自 foo.prototype
  • 构造函数 foo 被执行。执行的时候,相应的传参会被传入,同时上下文 (this)会被指定为这个新实例。new foo 等同于 new foo(),只能用在不传递任何参数的情况
  • 如果构造函数返回了一个“对象”,那么这个对象会取代整个 new 出来的结果。如果构造函数没有返回对象,那么 new 出来的结果为步骤 1 创建的对象
// 代码模拟 new 函数执行的过程
var new2 = function(func) {
    var o = Object.create(func.prototype);
    var k = func.call(o);
    if (typeof k === "object") {
        return k;
    } else {
        return o;
    }
};

new 的过程

  • 新生成了一个对象
  • 链接到原型
  • 绑定 this
  • 返回新对象
function create() {
    // 创建一个空的对象
    let obj = new Object();
    // 获得构造函数
    let Con = [].shift.call(arguments);
    // 链接到原型
    obj.__proto__ = Con.prototype;
    // 绑定 this,执行构造函数
    let result = Con.apply(obj, arguments);
    // 确保 new 出来的是个对象
    return typeof result === "object" ? result : obj;
}

你可能感兴趣的:(prototype)