试图在node.js上模拟function.bind()

时间:2015-01-18 11:10:28

标签: javascript node.js

我使用节点 v0.10.28

我一直试图将函数bind()方法模拟为函数的原型,而且我遇到了一个奇怪的问题。

Function.prototype.bind = function() {
    var obj = arguments[0],
        argumentsArray = [],
        self = this;

    // since arguments is an object and we can't call .splice() on it
    for(var i in arguments) {
        argumentsArray.push(arguments[i]);
    }

    argumentsArray.splice(0,1);

    // The following throws error when running via node, works fine on browser
    //console.log(argumentsArray); 

    return function() {
        return self.apply(obj,argumentsArray);
    }
};


function sum(y,z) {
    return this.x + y + z; 
}

var obj = { x : 8},
    f, value;

f = sum.bind(obj,1,2);

value = f();

console.log(value);

请参考this fiddle,当我在via节点(node demo.js)中运行时,它有一些奇怪的行为。请参阅小提琴中注释的console.log(argumentsArray),取消注释,将其保存在文件中并通过节点运行会出现以下错误:

TypeError: Object #<Object> has no method 'log'

最后console.log(value)在通过节点运行时,在控制台上不打印任何内容。这似乎在浏览器上完美运行。

我是否遗漏了某些内容,或者节点在原型函数定义或其他任何内容中是否允许console.log()

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

因为console模块将其所有方法绑定到自身(请参阅source here)。这是为了你可以做的事情:

var log = console.log;

log('something');

console模块将在第一次使用时初始化。所以在线

// The following throws error when running via node, works fine on browser
console.log(argumentsArray); 

node会尝试初始化console模块,然后调用log方法。在模块初始化过程中,它会尝试将log方法绑定到自身here,因此会再次调用您的方法bindconsole模块将被视为已初始化,并且节点将尝试调用其log方法。但实际上console当时没有初始化。所以会抛出错误。

<强> PS

更简单地实现您想要做的事情:

Function.prototype.bind = function(context) {
    var args = [].slice.call(arguments, 1);
    var self = this;

    return function() {
         return self.apply(context, args.concat([].slice.call(arguments)));
    };
};