我试图在JavaScript中为功能 mixin工作。
该函数应该从old创建一个新对象,将mixin对象的属性添加到它,并返回新对象 - 同时不改变旧对象,以便可以按预期使用它。
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;
};
但它没有用。问题是旧对象仍在变异。
知道为什么吗?谢谢!
答案 0 :(得分:1)
您的代码不起作用,因为:
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]]
然后,您希望将mixin混合到newObj[[Prototype]]
中,使mixin(及其[[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
答案 1 :(得分:1)
@Dan - 与您的上一个答案和提供的小提琴引用一样...... http://jsfiddle.net/xe207yec/6/ ...由于第94,95行,代码示例未按预期记录。将其改为......
coffeeTypes = coffeeTypes.concat(peruvian);
coffeeSizes = coffeeSizes.concat(extraLarge);
......干得好。
我也抓住了机会,提供了一个额外的基于功能的混合组合方法,以便让整个事情自旋 - http://jsfiddle.net/xe207yec/8/
答案 2 :(得分:0)
我发现了什么是错的,所以我想回答我自己的问题。
首先我要说的是,这可能是一个奇怪的混合方式,所以不要相信我的话。
问题不在于我制作mixins的函数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());
});