原型链
创建对象有几种方法
var o1 = { name: "o1" }; // 对象原型链指向 object,故此归为一类
var o2 = new Object({ name: "o2" });
var M = function(name) {
this.name = "o3";
};
var o3 = new M("o3");
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;
}
网友评论