原型继承
- JavaScript 中,所有的对象都有一个隐藏的
[[Prototype]]属性,它可以是另一个对象或者null。 - 我们可以使用
obj.__proto__进行访问(还有其他方法,但很快就会被覆盖)。 [[Prototype]]引用的对象称为“原型”。- 如果我们想要读取
obj属性或者调用一个方法,而且它不存在,那么 JavaScript 就会尝试在原型中查找它。写/删除直接在对象上进行操作,它们不使用原型(除非属性实际上是一个 setter)。 - 如果我们调用
obj.method(),而且method是从原型中获取的,this仍然会引用obj。因此方法重视与当前对象一起工作,即使它们是继承的。
函数原型
当用 new F() 创建一个新对象时,该对象的 [[Prototype]] 被设置为 F.prototype
prototype只出现在构造函数上
obj.__proto__ === Object.prototype
原生的原型
所有的内置原型顶端都是 Object.prototype。有些时候人们说“一切都从对象上继承而来”。

- 所有的内置对象都遵循一样的模式:
- 方法都存储在原型对象上(
Array.prototype、Object.prototype、Date.prototype等)。 - 对象本身只存储数据(数组元素、对象属性、日期)。
- 方法都存储在原型对象上(
- 基本数据类型同样在包装对象的原型上存储方法:
Number.prototype、String.prototype和Boolean.prototype。只有undefined和null没有包装对象。 - 内置对象的原型可以被修改或者被新的方法填充。但是这样做是不被推荐的。只有当添加一个还没有被 JavaScript 引擎支持的新方法的时候才可能允许这样做。
模拟new
new操作符做了这些事:
- 它创建了一个全新的对象
- 它会被执行[[Prototype]](也就是proto)链接
- 它使this指向新创建的对象
- 通过new创建的每个对象将最终被[[Prototype]]链接到这个函数的prototype对象上
- 如果函数没有返回对象类型Object(包含Functoin, Array, Date, RegExg, Error),那么new表达式中的函数调用将返回该对象引用
- 新生成了一个对象
- 链接到原型
- 绑定 this
- 返回新对象
// objectFactory(constructor, 'cxk', '18')function objectFactory() {// 创建一个空的对象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}
模拟Object.create
Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的proto。
// 模拟 Object.createfunction create(proto) {function F() {}F.prototype = proto;return new F();}
实现instanceOf
instanceof 可以正确的判断对象的类型,因为内部机制是通过判断对象的原型链中是不是能找到类型的 prototype。
// 模拟 instanceoffunction instance_of(L, R) {//L 表示左表达式,R 表示右表达式var O = R.prototype; // 取 R 的显示原型L = L.__proto__; // 取 L 的隐式原型while (true) {if (L === null) return false;if (O === L)// 这里重点:当 O 严格等于 L 时,返回 truereturn true;L = L.__proto__;}}
实现一个call
- 将函数设为对象的属性
- 执行&删除这个函数
- 指定this到函数并传入给定参数执行函数
- 如果不传入参数,默认指向为 window
Function.prototype.myCall = function (context) {const context = context || window// 给 context 添加一个属性// getValue.call(a, 'yck', '24') => a._func = getValuecontext._func = this// 将 context 后面的参数取出来const args = [...arguments].slice(1)// getValue.call(a, 'yck', '24') => a._func('yck', '24')const result = context._func(...args)// 删除 _funcdelete context._funcreturn result;}
