javascript---原型链

205 阅读3分钟

什么是原型链

每个实例化的对象都会有一个_proto_指向构造函数的prototype,这样一个指向形成的链路为原型链. 当访问一个对象的属性的时候,如果在当前的对象上没有匹配到,就会在对象的原型上去匹配,直到原型链的末尾Object.prototype. 原型链的作用是为了实现对象的继承.

遵循ECMAScript标准,someObject.[[Prototype]] 符号是用于指向 someObject 的原型。从 ECMAScript 6 开始,[[Prototype]] 可以通过 Object.getPrototypeOf() 和 Object.setPrototypeOf() 访问器来访问。这个等同于 JavaScript 的非标准但许多浏览器实现的属性 proto

但它不应该与构造函数 func 的 prototype 属性相混淆。被构造函数创建的实例对象的 [[Prototype]] 指向 func 的 prototype 属性。Object.prototype 属性表示 Object 的原型对象。

// 原型链的访问
var Fun = function (){
  this.activeValue = '我是原型上的activeValue';
  this.defaultValue= '我是原型上的默认值';
  this.getDefault= function() {
    return this.defaultValue;
  };
  this.setDefaultValue = function(defaultValue) {
    this.defaultValue = defaultValue;
  };
}

var aFun = new Fun();
var bFun = new Fun();

aFun.defaultValue = '我是aFun上的默认值';
aFun.activeValue = '我是aFun上的activeValue';
bFun.defaultValue = '我是bFun上的默认值';
bFun.activeValue = '我是bFun上的activeValue';

// 实例化对象的_proto_ 等于 构造函数的prototype
console.log(Fun.prototype);
console.log(aFun.__proto__);
console.log(aFun.__proto__ === Fun.prototype); // true

console.log(bFun.__proto__);
console.log(bFun.__proto__ === Fun.prototype); // true

/**
 * 原型链查找属性
 * 是当前对象的属性吗? 是的,显示该属性值;原型链上也有该属性,但是访问不到,这种情况称为属性遮蔽
 * 不是,那就在原型上查找,直到原型链末尾null
 * 找不到返回undefined
 */
console.log(Fun.defaultValue); // 我是原型上的默认值

console.log(aFun.defaultValue); // 我是aFun上的默认值
console.log(aFun.activeValue); // 我是aFun上的activeValue
console.log(aFun.stringValue); // undefined

console.log(bFun.defaultValue); // 我是bFun上的默认值
console.log(bFun.activeValue); // 我是bFun上的activeValue
console.log(bFun.stringValue); // undefined

prototype constructor __proto__的概念

prototype 是函数的原型对象,是函数所独有的;可以给函数和对象添加可共享(继承)的方法、属性

_proto_ 是原型链查询中实际用到的,它总是指向 prototype;是构造函数的原型对象;是对象独有的

constructor 每个函数都有一个原型对象,该原型对象有一个constructor属性,指向创建对象的函数本身。

原型对象通过constructor属性指向构造函数;实例通过[Prototype]属性指向原型对象

以下为摘抄部分,我觉得讲的比较好的,可以参考

1、proto 是原型链查询中实际用到的,它总是指向 prototype
2、prototype 是函数所独有的,在定义构造函数时自动创建,它总是被 proto 所指。
所有对象都有__proto__属性,函数这个特殊对象除了具有__proto__属性,还有特有的原型属性prototype。prototype对象默认有两个属性,constructor属性和__proto__属性。prototype属性可以给函数和对象添加可共享(继承)的方法、属性,而__proto__是查找某函数或对象的原型链方式。constructor,这个属性包含了一个指针,指回原构造函数。 作者:super_wei 链接:www.jianshu.com/p/08c07a953… 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

new操作符

在执行new操作符的时候,会进行以下步骤
1创建空对象;
2空对象的原型指针指向构造函数的原型对象;
3利用函数的call方法改变this指向,在空对象上挂载属性或方法;
4返回对象。

function _new (Func, ...args) {
  let obj = {};
  obj.__proto__ = Func.prototype;
  let result = Func.call(obj, ...args);
  return typeof result === 'object' ? result :obj;
}

instance of操作符

检测一个对象是否是另个对象new出来的实例.

//假设instanceof运算符左边是a,右边是b
a instanceof b
//instanceof运算时,通过判断L的原型链上是否存在b.prototype
a.proto.proto ..... === b.prototype ?
//如果存在返回true 否则返回false