Function.prototype.bind示例

时间:2015-07-20 09:49:21

标签: javascript bind



function Person(arg) {
	if (this.name == undefined) 	this.name = arg ? arg : "tom";
	console.log("Name: " + this.name);
}
Person.prototype.setName = function(value) {
	this.name = value;
};
Person.prototype.getName = function() {
	return this.name;
};
var myobj = {name : "james"};
var new_func = Person.bind(myobj);
new_func();					// Name: james
var obj = new new_func();			// Name: tom
console.log(obj.getName());			// tom




有没有人可以解释为什么最后两个代码显示我" tom"而不是" james"?

在我的想法中,new_func将myobj绑定到Person构造函数,因此obj Object应该是Person的一个实例,并且它应该绑定到myobj。但它看起来完全不同。

5 个答案:

答案 0 :(得分:1)

让我们分析一下代码。

var myobj = {name : "james"};
var new_func = Person.bind(myobj);
new_func();                 // Name: james
var obj = new new_func();           // Name: tom
console.log(obj.getName());         // tom

首先声明一个对象文字,其中有一个密钥,您打算将其用作未来新 Person 的属性。

接下来,您将new_func分配给 Person myObj 的绑定。 这样,构造函数Person被绑定到对象文字。但是,您正在使用该函数体创建一个新函数。当然你可以调用它,但不会创建任何新对象。

如果您只想提供 Person name ,最好选择通过构造函数参数来完成。

function Person (name) {
    this.name = name;
}

使用新的

调用它
var p1 = new Person("James");
console.log(p1.name);

但是,如果要创建另一个的现有对象实例,则应使用Object.create([...].prototype)

var myobj = Object.create(Person.prototype);
var myobj.name = "james";

console.log(myobj instanceof Person);

答案 1 :(得分:1)

如果我们检查polyfill是否为bind

Function.prototype.bind = function(oThis) {
    if (typeof this !== 'function') {
      // closest thing possible to the ECMAScript 5
      // internal IsCallable function
      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    }

    var aArgs   = Array.prototype.slice.call(arguments, 1),
        fToBind = this,
        fNOP    = function() {},
        fBound  = function() {

          return fToBind.apply(this instanceof fNOP
                 ? this
                 : oThis,
                 aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();

    return fBound;
  };

在代码中我们可以看到apply是基于以下条件使用对象调用的   this instanceof fNOP ? this : oThis,其中oThis在我们的案例中为myobj,并且创建了fNOP以通过bind为新创建的方法创建原型链接。因此,当我们使用new operator new new_func()时,这将是fNOP的一个基准。因此,当前对象将是this而不是myobj

答案 2 :(得分:0)

在您使用bind的情况下,您正在使用Person的相同函数体创建一个新的绑定函数

当您调用它来创建new Person实例时,您没有传递任何参数,因此它将使用默认参数{{1创建一个新元素名字。

您可以从bind()文档中读取:

  

bind()函数创建一个新函数(一个绑定函数),它具有相同的函数体(ECMAScript 5术语中的内部调用属性),因为它被调用的函数(绑定函数的目标函数)具有此值绑定到bind()的第一个参数,它不能被覆盖。 bind()还接受在调用绑定函数时提供给目标函数的前导默认参数。

在以下说明中:

<强> 1)

Tom

您使用new_func(); 作为此参考号召唤new_func()

<强> 2)

myobj

使用默认参数var obj = new new_func(); 创建一个实例。

<强>解决方案:

obj.name = "Tom"

答案 3 :(得分:0)

  

为什么最后两个代码显示“汤姆”而不是“詹姆斯”?

因为bind确实返回“绑定函数”,这在[[call]] ed时不同,但不会改变[[construct]]离子的行为。 bind构造函数是不可能的,new将始终创建一个新实例并忽略绑定值。

你不应该在构造函数上使用bind,它适用于方法。为了进一步说明会发生什么,请参阅此示例:

function Person(arg) {
    console.log("uninitialised", this);
    this.name = arg;
}
var o = {name: "james"};
var bound = Person.bind(o);

var x = new bound("frank"); // uninitialised Person {}
console.log(x); // Person {name: frank}
console.log(o); // Object {name: james}

var x = bound("frank"); // uninitialised Object {name: james}
console.log(x); // undefined
console.log(o); // Object {name: frank}

答案 4 :(得分:-1)

你必须绑定函数本身,尝试这样做:

obj.getName().bind(myobj);

根据Mozilla的例子,你只能在函数See documentation上调用bind