我最近Object.create()
在JavaScript中偶然发现了这个方法,并试图推断它与创建一个对象的新实例有什么不同new SomeFunction()
,当你想要使用另一个时.
请考虑以下示例:
var test = {
val: 1,
func: function() {
return this.val;
}
};
var testA = Object.create(test);
testA.val = 2;
console.log(test.func()); // 1
console.log(testA.func()); // 2
console.log('other test');
var otherTest = function() {
this.val = 1;
this.func = function() {
return this.val;
};
};
var otherTestA = new otherTest();
var otherTestB = new otherTest();
otherTestB.val = 2;
console.log(otherTestA.val); // 1
console.log(otherTestB.val); // 2
console.log(otherTestA.func()); // 1
console.log(otherTestB.func()); // 2
Run Code Online (Sandbox Code Playgroud)
请注意,在两种情况下都观察到相同的行为.在我看来,这两种情况之间的主要区别是:
Object.create()
实际使用的对象实际上形成了新对象的原型,而在new …
Javascript 1.9.3/ECMAScript 5介绍Object.create
道格拉斯·克罗克福德等人长期以来一直在倡导.如何new
在下面的代码中替换Object.create
?
var UserA = function(nameParam) {
this.id = MY_GLOBAL.nextId();
this.name = nameParam;
}
UserA.prototype.sayHello = function() {
console.log('Hello '+ this.name);
}
var bob = new UserA('bob');
bob.sayHello();
Run Code Online (Sandbox Code Playgroud)
(假设存在MY_GLOBAL.nextId).
我能想到的最好的是:
var userB = {
init: function(nameParam) {
this.id = MY_GLOBAL.nextId();
this.name = nameParam;
},
sayHello: function() {
console.log('Hello '+ this.name);
}
};
var bob = Object.create(userB);
bob.init('Bob');
bob.sayHello();
Run Code Online (Sandbox Code Playgroud)
似乎没有任何优势,所以我想我没有得到它.我可能过于新古典主义了.我应该如何使用MY_GLOBAL.nextId
创建用户'bob'?
在JavaScript中,这两个示例之间的区别是什么:
先决条件:
function SomeBaseClass(){
}
SomeBaseClass.prototype = {
doThis : function(){
},
doThat : function(){
}
}
Run Code Online (Sandbox Code Playgroud)
继承示例A使用Object.create:
function MyClass(){
}
MyClass.prototype = Object.create(SomeBaseClass.prototype);
Run Code Online (Sandbox Code Playgroud)
继承示例B使用new关键字
function MyClass(){
}
MyClass.prototype = new SomeBaseClass();
Run Code Online (Sandbox Code Playgroud)
这两个例子似乎做同样的事情.你什么时候选择一个而不是另一个?
另一个问题:考虑下面链接中的代码(第15行),其中对函数自身构造函数的引用存储在原型中.为什么这有用?
https://github.com/mrdoob/three.js/blob/master/src/loaders/ImageLoader.js
摘录(如果您不想打开链接):
THREE.ImageLoader.prototype = {
constructor: THREE.ImageLoader
}
Run Code Online (Sandbox Code Playgroud) 考虑这样一个带有原型链的对象:
var A = {};
var B = Object.create(A);
var C = Object.create(B);
Run Code Online (Sandbox Code Playgroud)
如果C在其原型链中有A,如何检查运行时?
instanceof
不合适,因为它的设计与构造函数一起使用,我在这里没有使用它.
告诉我,如果我错了:
原型是普通对象.当一个对象继承原型时,它不仅仅复制原型的属性,该对象存储对原型的引用.
在Firefox中,我可以这样做:
var food = {fruit:"apple"};
var more_food = {vegetable:"celery"};
food.__proto__ = more_food;
food.vegetable // celery
food.fruit // apple
Run Code Online (Sandbox Code Playgroud)
我可以使用该__proto__
属性手动设置对原型对象的引用.
我也可以用Object.create
:
var food = {fruit:"apple"};
var more_food = {vegetable:"celery"};
food = Object.create(more_food);
food.vegetable // celery
food.fruit // undefined
Run Code Online (Sandbox Code Playgroud)
究竟在Object.create
做什么?变量食物是否分配了对原型more_food的引用,或者是Object.create只返回对象的副本more_food?如果Object.create
只是制作副本,那么如果变量食物没有引用more_food,原型链如何工作?
我如何继承Object.create()?我试过这些,但都没有工作:
var B = function() {};
var A = function() {};
A = Object.create(B);
A.prototype.C = function() {};
Run Code Online (Sandbox Code Playgroud)
和
var B = function() {};
var A = function() {};
A.prototype.C = function() {};
A = Object.create(B);
Run Code Online (Sandbox Code Playgroud)
和
var B = function() {};
A = Object.create(B);
var A = function() {};
A.prototype.C = function() {};
Run Code Online (Sandbox Code Playgroud)
没有任何效果.我该如何使用这个新的Object.create()函数?
考虑以下代码:
var obj1 = Object.create({}, {myProp: {value: 1}});
var obj2 = Object.assign({}, {myProp: 1});
Run Code Online (Sandbox Code Playgroud)
是否有任何区别obj1
,obj2
因为每个对象都以不同的方式创建?
在一个项目中,我维护我们广泛使用null原型对象作为穷人的替代(仅限字符串键)映射,这些映射在许多较旧的ES6之前的浏览器中不是本机支持的.
基本上,要动态创建一个null原型对象,可以使用:
var foo = Object.create(null);
Run Code Online (Sandbox Code Playgroud)
这保证了新对象没有继承属性,例如"toString","constructor","__ proto__",这对于这个特定的用例是不可取的.
由于这种模式在代码中多次出现,我们提出了编写构造函数的想法,该构造函数将创建其原型具有null原型且没有自己的属性的对象.
var Empty = function () { };
Empty.prototype = Object.create(null);
Run Code Online (Sandbox Code Playgroud)
然后,要创建一个没有自己或继承属性的对象,可以使用:
var bar = new Empty;
Run Code Online (Sandbox Code Playgroud)
为了提高性能,我编写了一个测试,并发现在Object.create
所有浏览器中,本机方法的意外执行速度比涉及带有ad hoc原型的额外构造函数的方法慢得多:http://jsperf.com/blank-object - 创造.
我非常期待后一种方法更慢,因为它涉及调用用户定义的构造函数,这在前一种情况下不会发生.
造成这种性能差异的原因是什么?
我遇到过Douglas Crockfords Object.create方法的特殊性,我希望有人可以解释一下:
如果我创建一个对象 - 比如'person' - 使用对象文字符号,那么使用Object.create创建一个新对象 - 比如'anotherPerson' - 它继承了初始'person'对象的方法和属性.
如果我然后更改第二个对象的名称值 - 'anotherPerson' - 它还会更改初始'person'对象的名称值.
这只发生在嵌套属性时,这段代码应该让你知道我的意思:
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
};
// initiate new 'person' object
var person = {
name: {
first: 'Ricky',
last: 'Gervais'
},
talk: function() {
console.log('my name is ' + this.name.first + ' ' + this.name.last);
}
}
// create anotherPerson from person.prototype
var anotherPerson = …
Run Code Online (Sandbox Code Playgroud) 我一直在阅读了关于克罗克福德的垫片,以防止原型的改写,并了解它的不是结束,所有的/是的解决办法的时候.我也明白,ES5 Shim可能是一个可行的替代品.我还阅读了这篇文章,它提供了一个更强大,更安全的选择.
不过,我想知道他的Object.create
垫片是什么"说"然后"做".如果我的解释评论是正确的,有人可以告诉我吗?
if (typeof Object.create === 'undefined') {
//If the browser doesn't support Object.create
Object.create = function (o) {
//Object.create equals an anonymous function that accepts one parameter, 'o'.
function F() {};
//Create a new function called 'F' which is just an empty object.
F.prototype = o;
//the prototype of the 'F' function should point to the
//parameter of the anonymous function.
return new F();
//create a new constructor function based off of …
Run Code Online (Sandbox Code Playgroud) javascript ×10
object-create ×10
inheritance ×4
constructor ×2
object ×2
prototype ×2
instanceof ×1
new-operator ×1
performance ×1