20160120

you dont know js(this)

3. Explicit Binding(显示绑定)

用 call() 或者 apply() 的第一个参数是 this,可以用来显示绑定 this。

1.function foo(){
2. console.log(this.a);
3.}
4.var obj={
5. a: 2;
6.}
7.foo.call(obj);

用显示绑定通过 foo.call() 调用 foo,允许我们指定 this 为 obj

If you pass a simple primitive value (of type string, boolean, or number) as the this binding, the primitive value is wrapped in its object-form (new String(..), new Boolean(..), or new Number(..), respectively). This is often referred to as “boxing”.

如果你通过一个原始值(像是 string,boolean 或 number 类型,这个原始值包裹对象的形式((new String(..), new Boolean(..), or new Number(..)),通常被称为“boxing”

不幸的是,显示绑定并没有解决前面提到的问题,函数失去它的目标绑定等等。

Hard Binding(硬式绑定)

但是变化了模式的显示绑定确实有用, 思考下面的例子:

1.function foo(){
2. console.log(this.a);
3.}
4.var obj={
5. a: 2
6.};
7.var bar=function(){
8. foo.call(obj);
9.}
10.bar(); // 2
11.setTimeOut(bar,100); // 2
12.// bar hard bind foos this to obj
13.// so it cant be overwitten
14.bar.call(window); // 2

在 bar() 中调用 foo() 将 this 绑定到 obj,无论之后怎么调用 bar(),都会用 obj 调用 foo(),这个绑定明确又强烈,叫做硬式绑定。
The most typical way to wrap a function with a hard binding creates a pass-thru of any arguments passed and any return value received:

1.function foo(something){
2. console.log(this.a + something);
3. return(this.a + something);
4.}
5.var obj = {
6. a: 2
7.}
8.var bar = function(){
9. return foo.apply( obj, arguments );
10.};
11.
12.// 这里默认设置 this 为 2
13.var b = bar( 3 ); // 2 3
14.console.log( b ); // 5

另一种方式是创建一个可重用的助手。

1.function(something){
2. console.log(this.a,something);
3. return this.a + something;
4.}
5.var obj = {
6. a: 2
7.}
8.// 用 biind 函数帮助绑定
9.// 参数:函数对象,this 需要绑定的对象
10.function bind(fn, obj){
11. return function(){
12. return fn.apply( obj, arguments );
13. }
14.}
15.var bar = bind( foo,obj ); // 返回绑定好的函数
16.var b = bar( 3 );
17.console.log( b );

Since hard binding is such a common pattern, it’s provided with a built-in utility as of ES5: Function.prototype.bind, and it’s used like this
因为硬绑定是一个常见的模式,它提供了一个内置的 ES5 功能:Function.prototype.bind

1.function foo(something) {
2. console.log( this.a, something );
3. return this.a + something;
4.}
5.
6.var obj = {
7. a: 2
8.};
9.var bar = foo.bind(obj);
10.// 相当于
11.// var bar = function() {
12.// foo.call( obj );
13.// };
14.var b = bar(3); // 2 3
15.console.log(b); // 5

bind(..) returns a new function that is hard-coded to call the original function with the this context set as you specified.
bind() 返回一个新的函数是硬绑定去调用原始的函数设置 this 是你具体指定的值。

of ES6, the hard-bound function produced by bind(..) has a .name property that derives from the original target function. For example: bar = foo.bind(..) should have a bar.name value of “bound foo”, which is the function call name that should show up in a stack trace.
在 ES6 中,通过 bind() 方法硬绑定的函数有一个属性是 name 来自原来的目标函数。比如 bar = foo.bind() 中出现一个属性 bar.name 值为 bound foo,这个名字出现在堆栈跟踪。