var a = 2; function foo(){ console.log(this.a); } function bar(){ var a = 5; foo(); } bar(); // 2
function foo() { console.log( this.a ); } var obj2 = { a: 42, foo: foo }; var obj1 = { a: 2, obj2: obj2 }; obj1.obj2.foo(); // 42
function foo() { console.log( this.a ); } var obj = { a: 2, foo: foo }; var bar = obj.foo; // 这里bar将引用foo函数自己,因此不带有函数对象的上下文 var a = "oops, global"; // a是全局对象的属性 bar(); // "oops, global"
和回调函数的状况下(参数传递时的隐式赋值)git
function foo() { console.log( this.a ); } function doFoo(fn) { // 参数传递时,至关于fn = obj.foo,就和上个例子同样了 fn(); // <-- call-site! } var obj = { a: 2, foo: foo }; var a = "oops, global"; // `a` also property on global object doFoo( obj.foo ); // "oops, global"
function foo() { console.log( this.a ); } var obj = { a: 2 }; var bar = function() { foo.call( obj ); }; bar(); // 2 setTimeout( bar, 100 ); // 2 // 硬绑定后bar不管怎么调用,都不会影响foo函数的this绑定 bar.call( window ); // 2
硬绑定的典型应用是以下的包裹函数:github
function foo(something) { console.log( this.a, something ); return this.a + something; } var obj = { a: 2 }; var bar = function() { return foo.apply( obj, arguments ); // 将obj对象硬编码进去 }; var b = bar( 3 ); // 2 3 console.log( b ); // 5
即将内部函数用apply硬绑定到某个对象,不管怎么调用这个包裹函数,都不会影响内部函数的this。
bind辅助函数以下:浏览器
function foo(something) { console.log( this.a, something ); return this.a + something; } // simple `bind` helper function bind(fn, obj) { return function() { return fn.apply( obj, arguments ); // 利用参数将obj传入进去 }; } var obj = { a: 2 }; var bar = bind( foo, obj ); // bind( foo, obj )会返回一个包裹函数 var b = bar( 3 ); // 2 3 console.log( b ); // 5
总结:上述包裹函数,想要包裹其余函数,只能一个一个重复写,硬编码的方式致使不能被重用,当某种功能须要屡次重复使用时,将其抽象出来,成为函数。app
1. 建立一个新对象(若该函数不是JS内置的,则建立一个新的Object对象);
2. 将this绑定到这个对象;
3. 执行构造函数中的代码(为这个新对象添加属性);
4. 若函数没有返回其余对象,则自动返回这个新对象;若函数有return返回的是非对象,则仍是自动返回这个新对象,即覆盖那个非对象。函数
function foo(a) { this.a = a; } var bar = new foo( 2 ); console.log( bar.a ); // 2
function foo() { console.log( this.a ); } var a = 2; var o = { a: 3, foo: foo }; var p = { a: 4 }; o.foo(); // 3 (p.foo = o.foo)(); // 2,因为p.foo = o.foo的返回值是目标函数的引用,因此调用位置是foo(),而不是p.foo()或o.foo()
function foo() { // 返回一个箭头函数 return (a) => { // `this` here is lexically adopted from `foo()` console.log( this.a ); }; } var obj1 = { a: 2 }; var obj2 = { a: 3 }; // foo()不是箭头函数,他的this被绑定到obj1 var bar = foo.call( obj1 ); // foo.call( obj1 )返回箭头函数,因此bar为箭头函数 bar.call( obj2 ); // 2! 箭头函数的this没法被修改,new也不行
以下为和箭头函数同样的模式:oop
function foo() { var self = this; // lexical capture of `this` setTimeout( function(){ console.log( self.a ); }, 100 ); } var obj = { a: 2 }; foo.call( obj ); // 2