第五章 原型[[Prototype]]

属性设置和屏蔽

当执行obj.a这段代码,且a不直接存在于obj上时

  • 如果原型链上不存在aa就会被直接添加到obj
  • 如果存在,并且writeable: true,那么也会被直接添加到obj
  • 如果存在,但是writeable: false,那么即无法修改,也无法创建属性
  • 如果存在,并且它是一个setter,那不管怎么都会调用这个函数
  • 如果希望前面两种情况直接像第二种情况一样屏蔽掉原型链上的a,那么定义的属性的时候就不能使用=号,而是使用Object.defineProperty()来添加

类 函数

javaScript中,没有其他面向类的语言中的复制机制,你不能创建一个类的多个实例,只能创建多个对象,他们的[[Prototype]]关联的是同一个对象,默认情况下不会进行复制,因此这些对象之间不会完全失去联系他们是互相关联的

继承意味着复制操作,javaScript中不存在复制

构造函数

应该这样说,在javaScript中对于构造函数最准确的解释是,所有带new的函数调用

技术

注意constructor指向的可变性,即不一定指向创建它的那个函数

原型 继承

正确的原型继承应该像下面这样书写

function Foo(name) {
	this.name = name
}
Foo.prototype.myName = function () {
	return this.name
}
function Bar(name, label) {
	Foo.call(this, name)
	this.label = label
}
Bar.prototype = Object.create(Foo.prototype) // 这里是关键 创建一个新的对象,原型指向为Foo
Bar.prototype.constructor = Bar
Bar.prototype.myLabel = function() {
	return this.label
}
var a = new Bar("a", "obj a")
a.myName() // "a"
a.myLabel() // "obj a"

错误做法一

Bar.prototype = Foo.prototype

这种做法让BarFoo的原型指向同一个,当修改一个的原型的时候,会影响另一个

错误做法二

Bar.prototype = new Foo()

这个方法的确会创建一个关联到Bar.prototype的新对象,但是它使用了Foo的构造函数的调用,如果Foo有一些副作用(比如写日志,修改状态,注册到其他对象,给this添加数据属性等等),会影响到Bar的后代,后果严重

几种修改[[Prototype]]关联的方式

  • es6之前,Bar.prototype = Object.create( Foo.prototype )
  • es6,Object.setPrototypeOf( Bar.prototype, Foo.prototype)

检查类关系

  • instanceof: 这个方法只能处理对象和函数(带.prototype)之间的关系
  • Foo.prototype.isPrototypeOf(a),它的大体实现如下
function isPrototypeOf(a) {
	function F () {}
	F.prototype = this
	return a instanceof F
}
  • Object.getPrototypeOf(a):获取这个对象的[[Prototype]]
Object.getPrototypeOf(a) === Foo.prototype // 这样来使用它
  • 或者使用__proto__来获取[[Prototype]]链:它的大体实现如下
Object.definedProperty( Object.prototype, "__proto__", {
	get: function() {
		return Object.getPrototypeOf(this)
	},
	set: function(o) {
		Object.setPrototypeOf(this, o)
		return o
	}
})

Object.create(o)

它会创建一个新的对象,并把它关联到我们指定的对象,当参数为null时,会创建一个拥有空[[Prototype]]链接的对象,意思就是它不会有原型链,因此也非常适合用来做存储数据。它的大体实现如下

if (!Object.create) {
	Object.create = function (o) {
		function F () {}
		F.prototype = o
		return new F()
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值