先看call(或apply)的用处:
var first_object = { num: 42 }; function multiply(mult) { return this.num * mult; } multiply.apply(first_object, [5]); //等于 42*5
在上面的例子中,multiply是一个function,里面有this,所以,它必须“成为某个对象的方法才能执行”。这里的multiply函数中的this默认为全局的window对象:
function multiply(mult) { return this.num * mult; } window.num = 100; multiply(4); //等于 400
由于JavaScript是动态语言,一个对象的方法可以被变成另外的对象的方法,所以,该方法下的this会发生变化。
function multiply(mult) { return this.num * mult; } var book = { num : 33 }; book.total = multiply; book.total(10);
换种写法,采用new关键字
function multiply(mult) { return this.num * mult; } function Book(newNum) { this.num = newNum; } var book = new Book(33); book.total = multiply; book.total(10);
再看看下面的写法,和平时写的类比较像了:
function Book(newNum) { this.num = newNum; this.total = function (mult) { return this.num * mult; } } var book = new Book(33); book.total(10);
正因为this指针的不确定性,使得this所属函数定义的 和 实际执行的 上下文环境不同,从而计算出非预期的结果。
再看最初的代码示例,我们用js提供的call函数来解决this的问题。可以考虑给function函数原型增加一个bind方法------它只是封装了apply函数,返回值是一个function:
var first_object = { num: 42 }; function multiply(mult) { return this.num * mult; } Function.prototype.bind = function(obj) { //该行可换做 multiply.prototype.bind = function(obj) { var method = this; return function() { return method.apply(obj, arguments); }; } var foo = multiply.bind(first_object); foo(5);
(把bind方法建立在multiply的原型上也可,如注释所示)
总之,把正确的方法放在正确的对象里,才是bind方法的目的。请参看prototype.js关于bind方法的API:
http://www.prototypejs.org/api/function/bind
下面是prototype.js关于bind的源代码:
bind: function() { if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; var __method = this, args = $A(arguments), object = args.shift(); return function() { return __method.apply(object, args.concat($A(arguments))); } },
参考网址:
http://www.digital-web.com/articles/scope_in_javascript/