[JS] Topic - Object.create vs new
故事背景
Ref: 你不知道的javascript之Object.create 和new区别
var Base = function () {}
(1) var o1 = new Base(); (2) var o2 = Object.create(Base); // <----推荐
- (1) 使用的是__proto__
// var o1 = new Object(); o1.__proto__ = Base.prototype; Base.call(o1);
- (2) 使用的是prototype
Object.create = function (o) { var F = function () {}; F.prototype = o; return new F(); };
Object.create 失去了原来对象的属性的访问。
添加 Base.prototype.a = 3 后,依旧如此。
如此一来,得到的效果就是:
"通过Object.create构造的话,是连Base原型上的属性都访问不到的。"
因为他压根就没有指向他的prototype!
__proto__
和 prototype 的区别
Ref: js中__proto__和prototype的区别和关系?
* 显式原型 explicit prototype property:
* 隐式原型 implicit prototype link:
* 二者的关系:
隐式原型指向创建这个对象的函数(constructor)的prototype
1. 对象字面量的方式
这个对象是通过对象字面量构造出来的。
var person1 = { name: 'cyl', sex: 'male' };
形如这个形式的叫做对象字面量。构造出的对象,其[[prototype]]指向Object.prototype。
2. new 的方式
这个对象是由构造函数构造出来的。
function Person(){} var person1 = new Person();
通过new操作符调用的函数就是构造函数。由构造函数构造的对象,其[[prototype]]指向其构造函数的prototype属性指向的对象。
每个函数都有一个prototype属性,其所指向的对象带有constructor属性,这一属性指向函数自身。(在本例中,person1的[[prototype]]指向Person.prototype)
3. ES5中的Object.create()
这个对象是由函数Object.create构造的。
var person1 = { name: 'cyl', sex: 'male' }; var person2 = Object.create(person1);
解析:
function object(o){ function F(){} F.prototype = o; return new F() }
如下可见:person2.__proto__ === person1 ==== person1.prototype
//以下是用于验证的伪代码 var f = new F(); //于是有 f.__proto__ === F.prototype //true //又因为 F.prototype === o;//true //所以 f.__proto__ === o;
正视历史
Why we need Prototype 模式?
Ref: Javascript继承机制的设计思想
Brendan Eich想到C++和Java使用new命令时,都会调用"类"的 构造函数(constructor)。
他就做了一个简化的设计,在Javascript语言中,new命令后面跟的不是类,而是构造函数。
起因:prototype属性的引入 - 为了解决属性共享问题
为构造函数设置一个prototype属性,包含一个对象(以下简称"prototype对象"),所有实例对象需要共享的属性和方法,都放在这个对象里面;
那些不需要共享的属性和方法,就放在构造函数里面。
构造函数de验证方法:
alert(cat1.constructor == Cat); //true alert(cat2.constructor == Cat); //true
alert(cat1 instanceof Cat); //true alert(cat2 instanceof Cat); //true
Prototype模式de验证方法:
alert(Cat.prototype.isPrototypeOf(cat1)); //true alert(Cat.prototype.isPrototypeOf(cat2)); //true
// 某一个属性到底是本地属性(非共享),还是继承自prototype
对象的属性(共享) alert(cat1.hasOwnProperty("name")); // true alert(cat1.hasOwnProperty("type")); // false
// 无所谓本地属性or共享属性 alert("name" in cat1); // true alert("type" in cat1); // true
Why we need __proto__ 模式?
Ref: js中__proto__和prototype的区别和关系?
对象具有属性__proto__,可称为隐式原型;
一个对象的隐式原型指向:构造该对象的构造函数的原型【向上的指针】,这也保证了实例能够访问在构造函数原型中定义的属性和方法。
方法这个特殊的对象,除了和其他对象一样有上述_proto_属性之外,还有自己特有的属性——原型属性(prototype),这个属性是一个指针,指向一个对象,这个对象的用途就是包含所有实例共享的属性和方法(我们把这个对象叫做原型对象)。
原型对象也有一个属性,叫做constructor,这个属性包含了一个指针,指回原构造函数。
(完)