1、什么是this?
this的绑定和函数声明的位置没有任何关系,只取决于函数调用的方式?
1.1调用位置
<!DOCTYPE html> <html> <head> <title></title> </head> <body> </body> <script type="text/javascript"> function baz(){ //调用栈 :baz console.log("baz") bar(); //bar的调用位置 } function bar(){ // 当前调用栈 baz --> bar console.log("bar"); foo(); //foo的调用位置 } function foo(){ // 当前调用栈 baz --> bar -->foo console.log("foo"); } baz(); //baz的调用位置 </script> </html>
2、绑定规则
2.1 默认绑定
不带任何修饰的函数引用调用,只能默认绑定。在非严格模式下,默认绑定才能绑定到全局对象。
<!DOCTYPE html> <html> <head> <title></title> </head> <body> </body> <script type="text/javascript"> function foo(){ // "use strict"; 使用严格模式会报错 var a =1 console.log(this.a) //2 } var a =2; foo(); </script> </html>
foo运行在非严格模式下,默认绑定到全局
<!DOCTYPE html> <html> <head> <title></title> </head> <body> </body> <script type="text/javascript"> function bar(){ "user strict"; foo(); } function foo(){ // foo运行在非严格模式下,默认绑定到全局 // 严格模式和非严格模式不应该混用 console.log(a) // 1 } var a =1; bar(); </script> </html>
2.2 隐式绑定、
<!DOCTYPE html> <html> <head> <title></title> </head> <body> </body> <script type="text/javascript"> function foo(){ console.log(this.a) //2 } var obj={ a:2, foo:foo, } var a = 100; obj.foo(); </script> </html>
隐式绑定规则会把foo这个函数调用中的this绑定到obj的上下文对象中,此时this.a === obj.a
2.2.1隐性绑定丢失
<!DOCTYPE html> <html> <head> <title></title> </head> <body> </body> <script type="text/javascript"> function foo(){ console.log(this.a) //100 } var obj={ a:2, foo:foo, } var a = 100; var baz = obj.foo; baz(); </script> </html>
<!DOCTYPE html> <html> <head> <title></title> </head> <body> </body> <script type="text/javascript"> function foo(){ console.log(this.a) //100 } var obj={ a:2, foo:foo, } var a = 100; function baz(fn){ fn(); //foo调用位置 } baz(obj.foo); </script> </html>
2.3显示绑定
2.3.1 硬绑定
<!DOCTYPE html> <html> <head> <title></title> </head> <body> </body> <script type="text/javascript"> function foo(){ console.log(this.a); //2 } var obj = { a:2, }; var a = 100; var bar = function(){ foo.call(obj); } bar(); bar.call(window) //2 硬绑定不可能在修改它的this </script> </html>
2.3.2new绑定
<!DOCTYPE html> <html> <head> <title></title> </head> <body> </body> <script type="text/javascript"> function foo(a){ this.a =a } var bar = new foo(2) console.log(bar.a); //2 </script> </html>
2.4 优先级
2.4.1 显示绑定比隐式绑定优先级高
<!DOCTYPE html> <html> <head> <title></title> </head> <body> </body> <script type="text/javascript"> function foo(){ console.log(this.a); } var obj1 ={ a:2, foo:foo, } var obj2 ={ a:3, foo:foo, } obj1.foo(); //2 obj2.foo(); //3 obj1.foo.call(obj2); //3 obj2.foo.call(obj1); //2 </script> </html>
2.4.2 new绑定优先级比隐式绑定优先级高
<!DOCTYPE html> <html> <head> <title></title> </head> <body> </body> <script type="text/javascript"> function foo(a){ this.a = a; } 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 </script> </html>
2.5 总结
1、函数是否在new中调用(new绑定)?如果是,this绑定的是新创建的对象。
var bar= new foo();
2、函数是否通过call,apply(显示绑定)或者硬绑定调用?如果是,this绑定的是指定对象
var bar = foo.call(obj1)
3、函数是否在某个上下文对象中调用(隐式绑定)?如果是,this绑定的是绑定的那个上下文对象。
4、如果都不是,使用默认绑定,严格模式下绑定到undefined,否则绑定到全局对象。