JavaScript原型

在js中,几乎所有的对象在创建时都会有一个非空的[[prototype]]属性,表示对其他对象的引用

[[prototype]]

当我们试图引用对象的属性时,会触发[[get]]操作,对于[[get]]操作来说,会先检查对象本身有没有这个属性,没有的话会沿着[[peototype]]来查找这个属性。

let anotherObject = {
	a:2
}
let myObject = Object.create(anotherObject);
console.log(myObject.a)

Object.create() 这个方法会创建一个新的对象,并将新对象的[[prototype]]关联到指定的对象

  1. 在示例代码中,在查找属性a时,先在myObject自身查找,没有的话沿着[[prototype]]在anotherObject上查找,如果anotherObject上没有属性a且它的[[prototype]]不为空的话,会继续查找下去,如果整条[[prototype]]链上都没有属性a,[[get]]操作会返回undefined。
  2. 使用for…in遍历对象以及in操作符时,也会沿着[[prototype]]链查找对象
[[prototype]]的源头

所有普通的[[prototype]]最终都会指向Object.prototype

属性的设置与屏蔽
let myObject = {};
myObject.a = 2;

在js中,给一个对象设置一个属性,并不是简单的添加或者修改一个属性,一般分为两种情况

  • 在myObject上有属性a,那么会直接修改myObject的a属性值
  • 在myObject上不存在属性a,会沿着原型链查找属性a,如果整个原型链上都不存在属性a,会在myObject上添加a属性

当myObject上有属性a,且它的原型链上也存在属性a,就会发生屏蔽,屏蔽又分为了几种情况

  • 在原型链上存在名为a的普通数据访问属性且不是只读属性(writeable:false),那么会被赋值到myObject对象上
  • 在原型链上存在名为a的普通数据访问属性且是只读属性(writeable:true),非严格模式下回忽略这条赋值语句,严格模式下会报错
  • 如果在[[Prototype]]链上层存在foo并且它是一个setter,那就一定会调用这个setter。a不会被添加到myObject,也不会重新定义a这个setter
原型继承

当我们想把一个对象关联到另一个对象上时,通常有以下两种做法

// 第一种
let obj1 = Object.create(obj2)
// 第二种
Object.setPrototypeOf(obj1, obj2)

第一种方法会有轻微的性能损失,因为我们需要创建一个新的对象并且抛弃旧的对象,抛弃的旧对象需要进行垃圾回收。
第二种方法是es6添加的辅助函数。
如果不考虑轻微的性能损失,第一种要比第二种更简短易读。

查找一个对象的委托对象
  • instanceOf:用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
// instanceOf操作符左操作数是普通对象,右操作数是一个构造函数
a instanceOf Foo
// 对上述的表达式,instanceOf的回答是在a的整条原型链上是否有指向Foo.prototype的对象

instanceOf只能判断对象跟函数之间的关系,如果要判断两个对象之间的关系,instanceOf是做不到的

  • isPrototypeOf : 用于测试一个对象是否存在于另一个对象的原型链上
a.isPrototypeOf(b)
// a是否出现在了b的原型链上

我们可以通过Object.getProrotypeOf()来获取一个对象的原型链

function Foo() {};
let a = new Foo();
console.log(Object.getPrototypeOf(a) === Foo.prototype) // true

绝大多数的浏览器也支持__proto__来访问内部的原型链

function Foo() {};
let a = new Foo();
console.log(a.__proto__ === Foo.prototype) // true

__proto__是基于Object.getPrototyoeOf()的,其内部实现大致是这样的

Object.defineProperty(Object.prototype, '__proto_', {
	get() {
		return Object.getPrototypeOf(this)
	}
	set(o) {
		Object.setPrototypeOf(this, o)
	}
})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值