导图社区 JavaScript动态this值
this是JavaScript 语言的一个关键字。它是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用,收藏下图学习吧!
编辑于2021-09-20 03:59:12动态this值
定义
this 始终指向当前函数的调用者
this不是编写时绑定,而是运行时绑定。
this既不是函数自身的引用,也不是函数词法作用域的引用
this实际上是在函数被调用时建立的一个绑定,它指向 什么 是完全由函数被调用的调用点来决定的。
隐含绑定(Implicit Binding)
function foo() { console.log(this.a); } var obj = { a: 2, foo: foo } obj.foo();// 2 var bar = obj.foo; var a = "oops, global"; bar();// oops, global
function foo() { console.log(this.a); } function doFoo() { foo(); } var obj = { a: 2, foo: foo } var a = "oops, global"; doFoo(obj.foo);// oops, global
function foo() { console.log(this.a); } var obj = { a: 2, foo: foo } var a = "oops, global"; obj.foo();// 2 setTimeout(obj.foo,100);// oops, global // 等同于var bar = obj.foo;传递了bar给timeout其内调用bar()此时的调用者是window setTimeout(function(){ obj.foo();// 2 },200);// oops, global
明确绑定(Explicit Binding)
call,apply,bind
function foo() { console.log(this.a); } var obj = { a: 2 } var a = "oops, global"; foo();// oops, global foo.call(obj)// 2
硬绑定(Hard Binding)
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`硬绑定到`obj` // 所以它不可以被再被覆盖 bar.call(window);// 2
bind由来
function foo(something) { console.log(this.a,something); return this.a + something; } var obj = { a: 2 } var bar = function(){ return foo.apply(obj,arguments); } var b = bar(3);// 2 3 console.log(b);// 5
function foo(something) { console.log(this.a,something); return this.a + something; } // 简单的`bind`帮助函数(提取封装) function bind(fn,obj){ return function(){ return foo.apply(obj,arguments); } } var obj = { a: 2 } var bar = bind(foo,obj); var b = bar(3);// 2 3 console.log(b);// 5
/** *由于 硬绑定 是一个如此常用的模式,它已作为ES5的内建工具提供:Function.prototype.bind,像这样使用 */ function foo(something) { console.log(this.a,something); return this.a + something; } var obj = { a: 2 } var bar = foo.bind(obj);// 它已作为ES5的内建工具提供:Function.prototype.bind var b = bar(3);// 2 3 console.log(b);// 5
new绑定(new Binding)
function foo(something) { this.a = something; } var obj1 = { foo: foo } var obj2 = {}; obj1.foo(2); console.log(obj1.a);// 2 obj1.foo.call(obj2,3); console.log(obj2.a);// 3 var bar = new obj1.foo(4); console.log(obj1.a);// 2 console.log(bar.a);// 4 new绑定 的优先级要高于 隐含绑定
function foo(something) { this.a = something; } var obj1 = {} var bar = foo.bind(obj1); bar(2); console.log(obj1.a);// 2 var baz = new bar(3); console.log(obj1.a);// 2 console.log(baz.a);// 3 /** * bar是硬绑定到obj1的,但是new bar(3)没有想我们期待的那样将obj1.a变为3。 * 反而,硬绑定(到obj1)的bar(..)调用 可以 被new所覆盖。 * 因为new被实施,我们得到一个名为baz的新创建的对象,而且我们确实看到baz.a的值为3 */
new可以覆盖 硬绑定
function foo(a,b){ console.log("a:"+a+",b:"+b); } // 将数组散开作为参数 foo.apply(null,[2,3]);// a:2, b:3 // 用`bind(..)`进化柯里化 var bar = foo.bind( null,2 ); bar( 3 );// a:2, b:3
间接引用
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的 结果值 是一个刚好指向底层函数对象的引用 */ p.foo();// 4
参考
你不懂 JS:this 是什么?
你不懂 JS:this 豁然开朗!
javscript中this指向 | Tsrot Space