之前从来没听说过JavaScript还有原生的bind函数,在pomelo项目的git上提问被吐槽了,于是恶补一下。mozilla的一篇guide把问题解释得很清楚,英文版请看这里,中文版请看这里,中文版并不是完全翻译,不过够达意了。如果我这篇文章中有什么没有写清楚的,可以再看mozilla的guide来进行深入理解。

bind函数是Function的原生子函数

bind函数是Function的子函数,请看mozilla页面上的nav,bind是在Function之后的。所以不是Function的对象是没有这个原生函数的,这点请先理解。

函数的scope问题

要理解函数的scope问题,这里看个例子:

[codesyntax lang="javascript"]

var pm = "this is global pm param value!";
var scopeTest = function() { return this.pm; };

scopeTest();
"this is global pm param value!"

[/codesyntax]

看上面的例子,你会发现,如果一个全局的函数scopeTest,其函数scope是window。为了解决函数定义的scope和参数问题,bind这个函数应运而生。

bind函数的官方解释

bind方法会创建一个新函数,称为绑定函数.当调用这个绑定函数时,绑定函数会以创建它时传入bind方法的第一个参数作为this,传入bind方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数.

语法:someFunction.bind(thisArg[, arg1[, arg2[, ...]]])

官方的范例:

[codesyntax lang="javascript"]

var x = 9; 
var module = {
  x: 81,
  getX: function() { return this.x; }
};

module.getX(); // 81

var getX = module.getX;
getX(); // 9, because in this case, "this" refers to the global object

// create a new function with 'this' bound to module
var boundGetX = getX.bind(module);
boundGetX(); // 81

[/codesyntax]

简单的范例理解

这里需要注意的是,bind后其实是会返回一个函数的,请重新定义函数来接受这个返回值。bind函数并不会改变原函数的构造。

[codesyntax lang="javascript"]

var pm = "this is global pm param value!";
var scopeTest = function() { return this.pm; };

scopeTest();
"this is global pm param value!"

var foo = { pm: "foo pm param value!" };
var newScopeTest = scopeTest.bind(foo);
newScopeTest();
"foo pm param value!"

[/codesyntax]

带参数的范例

[codesyntax lang="javascript"]

var pm = "this is global pm param value!";
var scopeTest = function(pm1, pm2) { return this.pm + ' ' + pm1 + ', ' + pm2; };

scopeTest();
"this is global pm param value! undefined, undefined"

var newScopeTest = scopeTest.bind(foo, "param1", "param2");
newScopeTest();
"foo pm param value! param1, param2"

var newScopeTest = scopeTest.bind(null, "param1", "param2");
newScopeTest();
"this is global pm param value! param1, param2"

[/codesyntax]

P.S 最后顺便留点尾巴,关于这篇文章最上面写的github上pomelo的问题的几个解答: