下面这段代码使用的就是典型的「原型风格」:
function Foo(name) { this.name = nameFoo.prototype.myName = function() { return this.namefunction Bar(namelable) { Foo.call(thisname) this.lable = lableBar.prototype = Object.create( Foo.prototype )// 注意 , 现在没有 Bar.prototype.constructor 属性了 , 如果你需要的话 , 要修复一下 , 不过大部分 , 你并不需要它 。 Bar.prototype.myLabel = function() { return this.lablevar a = new Bar('foo''bar')a.myName() // 'foo'a.myLabel() // 'bar'
这段代码的核心是语句 Bar.prototype = Object.creat( Foo.prototype ) 。 调用 Object.create(..) 会凭空创建一个新对象 , 并把新对象内部的 [[Prototype
关联到你指定的对象 , 在这里是 Bar.prototype 。
换句话说 , 这条语句的意思是:「创建一个新的 Bar.prototype 对象 , 并把它关联到 Foo.prototype 。 」
Object.create(..) 创建一个新对象 , 并把新对象的 [[Prototype
指向指定的对象 。
声明 function Bar() { ..时 , 和其他函数一样 , Bar 会有一个 prototype 关联到默认的对象 , 但是这个对象并不是我们想要的 Foo.prototype 。 因此我们创建了一个新对象并把它关联到我们希望的对象上面 , 直接把原始的关联对象抛弃掉 。
注意:下面这两种方式是常见的错误做法 , 实际上它们都存在一些问题:
Bar.prototype = Object.create( Foo.prototype ) 就是这句代码 。
// 和你想要的不一样!Bar.prototype = Foo.prototype;// 基本上满足你的需求 , 但是可能会产生一些副作用:Bar.prototype = new Foo()
Bar.prototype = Foo.prototype 并不会创建一个关联到 Bar.prototype 的新对象 , 它只是让 Bar.prototype 直接去引用 Foo.prototype 对象本身 。 显然这不是你想要的结果 , 否则你根本不需要 Bar 对象 , 直接使用 Foo 就可以了 , 这样代码也会简单一点 。
这里指的是 Bar.prototype = Object.create( Foo.prototype ) 替代品 。
Bar.prototype = Foo.prototype 是将 Foo 的原型对象指派给 Bar 的原型对象 , 这里为什么说想要的不一样呢?
Bar.prototype = new Foo() 的确会创建一个关联到 Bar.prototype 的新对象 。 但是它使用了 Foo(..) 的「构造函数调用」 , 如果函数 Foo 有一些副作用 , 比如写日志、修改状态等的话 , 就会影响 Bar 的后代 , 后果不堪设想 。
一个是引用 , 一个是创建新对象 。
因此 , 要创建一个合适的关联对象 , 我们必须使用 Object.create(..) 而不是具有副作用的 Foo(..) 。 这样做唯一的缺点就是需要创建一个新的对象然后把旧对象抛弃掉 , 不能直接修改已有的默认对象 。
这里并不想和 Foo 函数有关联 , 只是想和 Foo.prototype 有关联 。
如果能有一个标准并且可靠的方法来修改对象的 [[Prototype
Bar.prototype = Object.create( Foo.prototype ) 会直接覆盖掉原有的 Bar.prototype 默认对象 。 constructor 属性已经被覆盖无了 。
关联就好了 。 在 ES6 之前 , 我们只能通过设置 .proto 属性来实现 , 但是这个方法并不是标准 , 并且无法兼容所有的浏览器 。 ES6 添加了辅助函数 Object.setPrototypeOf(..) , 可以用标准并且可靠的方法来修改关联 。
.proto 是浏览器设置的属性 , 用来表示对象的原型 。
- 编程|芒果口袋携手阿里巴巴地推第一人王志坚又掀业内新浪潮——成就数字化行业新高度!
- 九江市疾控中心新冠肺炎疫情常态化防控相关防护指南——图书馆篇
- 软件|黑色基调 ——西数SN770评测
- 传统媒体|品牌出海:Facebook广告投放指南——优惠广告怎么创建?
- 通讯:血染的小白鞋——一位“猪湾事件”幸存者的控诉
- 惠普新一代轻薄本——星14青春版|惠普星14青春版开售:全新12代酷睿 仅4099元
- javascript|在B端和C端公司做公关,有什么区别?
- javascript|现在分布式、云智能时代,应用软件开发简直得JavaScript者得天下
- 携程|现在分布式、云智能时代,应用软件开发简直得JavaScript者得天下
- 云米|0—1999元手机性价比排名:OPPO K9 Pro上榜!