我的 JavaScript 混入函数有什么问题?
What's wrong with my function for JavaScript mixins?
我试图在 JavaScript 中获取一个适用于 functional mixin 的示例。
http://jsfiddle.net/xe207yec/3/
该函数应该从旧对象创建一个新对象,将 mixin 对象的属性添加到它,然后 return 新对象 - 同时不改变旧对象以便它可以按预期使用。
var plusMixin = function(oldObj, mixin) {
var newObj = oldObj;
newObj.prototype = Object.create(oldObj.prototype);
for (var prop in mixin) {
if (mixin.hasOwnProperty(prop)) {
newObj.prototype[prop] = mixin[prop];
}
}
return newObj;
};
但它不起作用。问题是旧对象仍在变异。
知道为什么吗?谢谢!
您的代码无效,因为:
var newObj = oldObj;
这是一个简单的赋值,意味着 newObj
现在指向与 oldObj
相同的对象。
newObj.prototype = Object.create(oldObj.prototype);
这可能是您想要的,也可能不是。如果 oldObj
是一个函数,那么这将起作用。如果 oldObj
不是一个函数(即一个普通的 Object 实例),那么这将不起作用,您将需要类似以下代码的内容:
var plusMixin = function(oldObj, mixin) {
// Construct the [[Prototype]] for the new object
var newObjPrototype = Object.create(Object.getPrototypeOf(oldObj));
// Mix-in the mixin into the newly created object
Object.keys(mixin).map(function(k) {
newObjPrototype[k] = mixin[k];
});
// Use this newly created and mixed-in object as the [[Prototype]] for the result
return Object.create(newObjPrototype);
};
依据:
你想要一个像这样的原型链:
newObj --> newObj[[Prototype]] --> oldObj[[Prototype]]
然后您想要将混音混入 newObj[[Prototype]]
,保持混音(及其 [[Prototype]]
不变。
用法:
function Foo() {};
Foo.prototype.hello = function() {}
function Bar() {};
Bar.prototype.goodbye = function() {}
var foo = new Foo();
var foobar = plusMixin(foo, Bar.prototype); // foobar now has hello and goodbye available to it
我发现哪里出了问题,所以我会回答我自己的问题。
首先我想说的是,这可能是一种奇怪的混合方式,所以不要相信我的话。
问题不在于我制作混入的函数,plusMixin
,而是使用它的示例代码。如果您查看问题中的 jsfiddle,我正在创建新的混合 类 错误。这是正确的用法:
// build new objects that are combinations of the above
// and put them into a new array
var coffees = coffeeTypes.reduce(function(previous, current) {
var newCoffee = coffeeSizes.map(function(mixin) {
// `plusMixin` function for functional mixins, see Ch.7
var newCoffeeObj = plusMixin(current, mixin);
return new newCoffeeObj();
});
return previous.concat(newCoffee);
},[]);
// we've now defined how to get the price and label for each
// coffee type and size combination, now we can just print them
coffees.forEach(function(coffee){
printPrice(coffee.getPrice(), coffee.getLabel());
});
@Dan - 与您的上一个答案和提供的 fiddle 参考一样... http://jsfiddle.net/xe207yec/6/ ... 由于第 94,95 行,代码示例未按预期记录。将其更改为 ...
coffeeTypes = coffeeTypes.concat(peruvian);
coffeeSizes = coffeeSizes.concat(extraLarge);
...完成任务。
我还借此机会提供了一个额外的基于纯函数的 mixin 组合方法,以便让整个事情变得有趣 - http://jsfiddle.net/xe207yec/8/
我试图在 JavaScript 中获取一个适用于 functional mixin 的示例。
http://jsfiddle.net/xe207yec/3/
该函数应该从旧对象创建一个新对象,将 mixin 对象的属性添加到它,然后 return 新对象 - 同时不改变旧对象以便它可以按预期使用。
var plusMixin = function(oldObj, mixin) {
var newObj = oldObj;
newObj.prototype = Object.create(oldObj.prototype);
for (var prop in mixin) {
if (mixin.hasOwnProperty(prop)) {
newObj.prototype[prop] = mixin[prop];
}
}
return newObj;
};
但它不起作用。问题是旧对象仍在变异。
知道为什么吗?谢谢!
您的代码无效,因为:
var newObj = oldObj;
这是一个简单的赋值,意味着 newObj
现在指向与 oldObj
相同的对象。
newObj.prototype = Object.create(oldObj.prototype);
这可能是您想要的,也可能不是。如果 oldObj
是一个函数,那么这将起作用。如果 oldObj
不是一个函数(即一个普通的 Object 实例),那么这将不起作用,您将需要类似以下代码的内容:
var plusMixin = function(oldObj, mixin) {
// Construct the [[Prototype]] for the new object
var newObjPrototype = Object.create(Object.getPrototypeOf(oldObj));
// Mix-in the mixin into the newly created object
Object.keys(mixin).map(function(k) {
newObjPrototype[k] = mixin[k];
});
// Use this newly created and mixed-in object as the [[Prototype]] for the result
return Object.create(newObjPrototype);
};
依据:
你想要一个像这样的原型链:
newObj --> newObj[[Prototype]] --> oldObj[[Prototype]]
然后您想要将混音混入 newObj[[Prototype]]
,保持混音(及其 [[Prototype]]
不变。
用法:
function Foo() {};
Foo.prototype.hello = function() {}
function Bar() {};
Bar.prototype.goodbye = function() {}
var foo = new Foo();
var foobar = plusMixin(foo, Bar.prototype); // foobar now has hello and goodbye available to it
我发现哪里出了问题,所以我会回答我自己的问题。
首先我想说的是,这可能是一种奇怪的混合方式,所以不要相信我的话。
问题不在于我制作混入的函数,plusMixin
,而是使用它的示例代码。如果您查看问题中的 jsfiddle,我正在创建新的混合 类 错误。这是正确的用法:
// build new objects that are combinations of the above
// and put them into a new array
var coffees = coffeeTypes.reduce(function(previous, current) {
var newCoffee = coffeeSizes.map(function(mixin) {
// `plusMixin` function for functional mixins, see Ch.7
var newCoffeeObj = plusMixin(current, mixin);
return new newCoffeeObj();
});
return previous.concat(newCoffee);
},[]);
// we've now defined how to get the price and label for each
// coffee type and size combination, now we can just print them
coffees.forEach(function(coffee){
printPrice(coffee.getPrice(), coffee.getLabel());
});
@Dan - 与您的上一个答案和提供的 fiddle 参考一样... http://jsfiddle.net/xe207yec/6/ ... 由于第 94,95 行,代码示例未按预期记录。将其更改为 ...
coffeeTypes = coffeeTypes.concat(peruvian);
coffeeSizes = coffeeSizes.concat(extraLarge);
...完成任务。
我还借此机会提供了一个额外的基于纯函数的 mixin 组合方法,以便让整个事情变得有趣 - http://jsfiddle.net/xe207yec/8/