什么对象javascript函数绑定(它的"this"是什么)?

esp*_*esp 19 javascript functional-programming function this ecmascript-5

我知道它在函数内部this.

var func = function {
    return this.f === arguments.callee; 
    // => true, if bound to some object
    // => false, if is bound to null, because this.f === undefined
}

var f = func; // not bound to anything;

var obj = {};
obj1.f = func; // bound to obj1 if called as obj1.f(), but not bound if called as func()

var bound = f.bind(obj2) // bound to obj2 if called as obj2.f() or as bound()
Run Code Online (Sandbox Code Playgroud)

编辑:

你实际上不能打电话,obj2.f()因为f它不会成为你的财产obj2

编辑结束.

问题是:如何找到函数绑定的对象,在这个函数之外?

我想实现这个目标:

function g(f) {
  if (typeof(f) !== 'function') throw 'error: f should be function';

  if (f.boundto() === obj)
    // this code will run if g(obj1.f) was called
    doSomething(f);

  // ....

  if (f.boundto() === obj2)
    // this code will run if g(obj2.f) or g(bound) was called
    doSomethingElse(f);
}
Run Code Online (Sandbox Code Playgroud)

和部分应用程序而不更改函数绑定的对象:

function partial(f) {
   return f.bind(f.boundto(), arguments.slice(1));
}
Run Code Online (Sandbox Code Playgroud)

共识:

你不能这样做.外卖:使用bindthis非常小心:)

Nat*_*all 11

部分申请

你可以做部分申请:

// This lets us call the slice method as a function
// on an array-like object.
var slice = Function.prototype.call.bind(Array.prototype.slice);

function partial(f/*, ...args */) {

    if (typeof f != 'function')
        throw new TypeError('Function expected');

    var args = slice(arguments, 1);

    return function(/* ...moreArgs */) {
        return f.apply(this, args.concat(slice(arguments)));
    };

}
Run Code Online (Sandbox Code Playgroud)

这个函数绑定到什么对象?

此外,对于问题的第一部分,还有一个非常直接的解决方案.不确定这是否适合您,但您可以很容易地在JS中修补问题.猴子修补bind是完全可能的.

var _bind = Function.prototype.apply.bind(Function.prototype.bind);
Object.defineProperty(Function.prototype, 'bind', {
    value: function(obj) {
        var boundFunction = _bind(this, arguments);
        boundFunction.boundObject = obj;
        return boundFunction;
    }
});
Run Code Online (Sandbox Code Playgroud)

只需在任何其他脚本运行之前运行它,以及任何使用的脚本bind,它将自动boundObject向该函数添加一个属性:

function f() { }
var o = { };
var g = f.bind(o);
g.boundObject === o; // true
Run Code Online (Sandbox Code Playgroud)

(注意:由于您正在使用,我假设您处于ES5环境中bind.)

  • 只要你修改 .bind 来捕获原来绑定的对象,你也可以捕获原来绑定的函数..然后你也可以支持重新绑定,这解决了其他人询问的一些相关场景。 (2认同)

jfr*_*d00 5

javascript 中的函数在技术上不受任何约束。它可以声明为对象的属性,如下所示:

var obj = {
    fn: function() {}
}
obj.fn();
Run Code Online (Sandbox Code Playgroud)

但是,如果您将函数单独放入它自己的变量中,则它不会绑定到任何特定对象。

例如,如果你这样做:

var obj = {
    fn: function() {}
}
var func = obj.fn;
func();
Run Code Online (Sandbox Code Playgroud)

然后,当您调用func()which 依次执行该fn()函数时,它与obj被调用时完全没有关联。将对象与函数关联是由函数的调用者完成的。它不是函数的属性。

如果要使用fn.bind(obj),则会创建一个新函数,该函数仅在内部执行对 的调用obj.fn()。它不会神奇地为 javascript 添加任何新功能。事实上,你可以在 MDN 上看到一个 polyfill.bind()来了解它是如何工作的。


如果您希望this无论函数如何调用都始终是一个特定的对象,那么 javascript 就不是这样工作的。除非一个函数实际上是一个 shim,它在被调用时强制与一个硬.bind()连线对象关联(是什么),那么一个函数没有一个硬连线关联。关联是由调用者根据调用函数的方式完成的。这与其他一些语言不同。例如,在 C++ 中,如果在调用时没有与之关联的正确对象,则无法调用函数。该语言根本无法解析函数调用,并且您会收到编译错误。

如果您在 javascript 中对类型进行分支,那么您可能没有正确使用该语言的面向对象功能或未发挥最大优势。