我的 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());
});

http://jsfiddle.net/xe207yec/6/

@Dan - 与您的上一个答案和提供的 fiddle 参考一样... http://jsfiddle.net/xe207yec/6/ ... 由于第 94,95 行,代码示例未按预期记录。将其更改为 ...

coffeeTypes = coffeeTypes.concat(peruvian);
coffeeSizes = coffeeSizes.concat(extraLarge);

...完成任务。

我还借此机会提供了一个额外的基于纯函数的 mixin 组合方法,以便让整个事情变得有趣 - http://jsfiddle.net/xe207yec/8/