JS中this的指向

JS中this的指向

JavaScript中的this总是指向一个对象,而具体指向哪个对象是在**运行时**基于函数的执行环境动态绑定的。

有位人说A.apply(x,array);等价于(A.bind(x))(array),现在看着挺对的,留待以后验证。

方法调用模式

  当函数作为对象的方法被调用时,this指向该对象。

普通函数调用模式

  this总是指向全局对象,在浏览器中,这个全局对象就是window对象。

但在使用**严格模式**"use strict";时,this在函数调用模式不会指向全局对象window,而是undefined。

构造器调用模式

  因为new运算符会返回一个指向构造器函数原型的对象,所以通常情况下this就指向返回的这个对象。

  关于new运算符的内部具体操作请见我博客中的“JS中new运算符详解”!

  但还有特殊的情况,比如构造器显式的返回了一个object类型的对象时,new调用构造器则会最终返回这个对象,而不是我们期待的this。

Function.prototype.apply调用模式

  详情见我博客中的“JS中的apply()使用详解”一文,它的第一个参数可以改变函数体内this对象的指向。

  如果我们传入的第一个参数是null或undefined,函数体内的this会指向全局对象,在浏览器中则是window。

1
2
3
4
5
var func=function(a,b,c){
alert(this===window);//true
};
func.apply(null,[1,2,3]);
func.apply(undefined,[1,2,3]);

  但如果是在严格模式下,则会严格执行第一个参数指定了函数体内this对象的指向,即传进来null,this就指向null;传进来undefined,this就指向undefined

1
2
3
4
5
var func=function(a,b,c){
"use strict";
alert(this===null);//true
};
func.apply(null,[1,2,3]);

闭包中的this指向

  每个函数在被调用时都会自动取得两个特殊变量:this和arguments。内部函数在搜索这两个变量时,只会搜索到其活动对象为止,因此闭包中永远不可能直接访问外部函数中的这两个变量,this一定是在这个闭包被调用时动态绑定的。如果想使用外层函数的this,最常用的方法就是找一个变量把它保存下来(eg:that)。

利用apply实现的bind函数

  Function.prototype.bind,用来指定函数内部的this指向,其简化版实现可以这样模拟:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Function.prototype.bind=function(context){
var that=this;//保存方法调用模式下被调用的原函数
return function(){//闭包返回一个新函数(可访问外层函数的变量和参数)
return that.apply(context,arguments);//改变that原函数的内部this指向为我们指定的context
}
};

var obj1={
name: "Daoma",
};

var func=function(){
alert(this.name);
};

func();//未定义

var func=function(){
alert(this.name);
}.bind(obj1);

func();//Daoma

  通常我们还会实现的稍微复杂一点,可以往func函数中预先填入一些参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Function.prototype.bind=function(){
var that=this,
context=[].shift.call(arguments),//将第一个元素删掉并返回
args=[].slice.call(arguments);//用slice的另一个功能将剩余的参数类数组转换成数组
return function(){
//这里运用了函数柯里化的思想,组合两次分别传入的参数,作为新函数的参数
return that.apply(context,[].concat.call(args,[].slice.call(arguments)));
}
};

var obj1={
name: "daoma",
};

var func=function(a,b,c,d){
alert(this.name);
alert([a,b,c,d]);
}.bind(obj1,1,2);

func(3,4);//即可以传参两次拼到一起

补充bind和call的返回值

  1. fun.bind(thisArg[, arg1[, arg2[, …]]])

  返回由指定的this值和初始化参数改造的原函数拷贝

  1. fun.call(thisArg, arg1, arg2, …)

  返回值是你调用的方法的返回值,若该方法没有返回值,则返回undefined。

最后我还有一个需要填的问题坑,留待以后实力提高后解决:JavaScript中Apply调用模式的this指向问题

文章目录
  1. 1. JS中this的指向
    1. 1.0.1. 方法调用模式
    2. 1.0.2. 普通函数调用模式
    3. 1.0.3. 构造器调用模式
    4. 1.0.4. Function.prototype.apply调用模式
    5. 1.0.5. 闭包中的this指向
  2. 1.1. 利用apply实现的bind函数
,