js中this的绑定

this是js中的一个关键字,它代表当前作用域的上下文环境,而且随着上下文的改变而动态变化。

this指当前的上下文环境,在不经意间容易改变:

 1 var info = "This is global info";
 2 var obj = {
 3     info: 'This is local info',
 4     getInfo: getInfo
 5 }
 6 function getInfo() {
 7     console.log(this.info);
 8 }
 9 obj.getInfo()    //This is local info
10 
11 getInfo()    //This is global info 当前上下文环境被修改了
12

这个例子告诉我们:

1、同一个函数,调用的方式不同,this的指向就会不同,结果就会不同

2、对象内部的属性的值为引用类型时,this的指向不会一只绑在原对象上。

其次,还有不经意间丢失this的情况:

 1 var info = "This is global info";
 2 var obj = {
 3     info: 'This is local info',
 4     getInfo: function getInfo() {
 5         console.log(this.info);
 6 
 7         var getInfo2 = function getInfo2() {
 8             console.log(this.info);
 9         }
10         getInfo2();
11     }
12 }
13 obj.getInfo();
14 
15 //This is local info
16 //This is global info

上面代码中,对象obj中定义了一个getInfo方法,方法内又定义了一个新的函数,也希望拿到最外层的该对象的info属性的值,但事与愿违,函数内部的this被错误地指向了window对象,这就导致了错误。

this实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪被调用。

this的绑定一共有四种绑定:1、默认绑定(即没有明确的调用对象)

                                             2、隐性绑定(即作为对象方法调用,this会被绑定到该对象)

                                             3、显性绑定(使用call()、apply()调用,两个方法的第一个参数为一个对象,this被绑定到该对象)

                                             4、new绑定(使用new来调用函数,会构造一个对象,并把this绑定到该对象)

一、默认绑定(即没有明确的调用对象)

1 function foo(){
2     var a = 1 ;
3     alert(this.a);
4 }
5 var a = 2;
6 foo();   //  2    (非严格模式下)

上面代码中,foo是在全局环境被调用的,所以this被绑定到window。但前提是非严格模式下,如果在严格模式下,this被绑定到undefined。

二、隐性绑定(即作为对象方法调用,this会被绑定到该对象)

1 function  foo(){
2       var  a = 1;
3       alert(this.a);
4 }
5 var  obj = {
6       a:2,
7       foo:foo
8 };
9 obj.foo();    // 2

上面代码中,obj对象调用foo函数,因此this被绑定到obj。

对象属性引用链中只有最后一层会影响调用位置。

 1 function  foo(){
 2         alert(this.a);
 3 }
 4 var  obj2 = {
 5       a:2,
 6       foo:foo
 7 };
 8 var obj1 = {
 9       a:1,
10       obj2:obj2 
11 }; 
12 obj1.obj2.foo(); //2

上面代码中,obj1和obj2两个对象连续调用,this会被绑定到最后一个对象,即obj2,所以输出2

三、显性绑定(使用call()、apply()调用,两个方法的第一个参数为一个对象,this被绑定到该对象)

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

call方法的参数若为空,默认调用window对象

       硬绑定——显示绑定的一种变形

                 优点:可以解决丢失绑定问题

                 缺点:硬绑定后不能再修改它的this

 1 function  foo(){
 2      alert(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.call(window);  // 2

ES5中提供了内置方法Function.prototype.bind

 1 function foo(something){
 2       alert(this.a, something);
 3       return  this.a + something;
 4 }
 5 var obj = {
 6     a:2
 7 };
 8 var  bar = foo.bind(obj);
 9 var  b = bar(3);   //  2  3
10 alert(b);   // 5

bind()会返回一个硬编码的新函数,它会把参数设置为this的上下文并调用原始函数

四、new绑定(使用new来调用函数,会构造一个对象,并把this绑定到该对象)

1 function   foo(a){
2       this.a = a;
3 }
4 var bar = new foo(2);
5 alert(bar.a);  // 2

上面代码中,bar对象是由foo函数创建得,因此继承了foo函数的属性和方法。

综上,this绑定的优先级为:new绑定  >  显示绑定  >  隐式绑定  >  默认绑定

前端面试中经常会问到一个问题:new操作符都干了些什么,回答的时候可以回答一下几点:

1、创建了一个空对象,并用this引用该对象,同时还继承了该函数的原型

2、属性和方法被载入到该函数的原型中

3、新创建的对象由this引用,并且最后隐式地返回this

1 var obj  = {};
2 obj.__proto__ = Base.prototype;
3 Base.call(obj);
原文地址:https://www.cnblogs.com/endlessmy/p/8576096.html