1 首先this是和执行上下文绑定的,而执行上下文分为三种:
(1) 全局执行上下文
在全局上下文中打印console.log(this),会发现最终是window,所以可以得出结论:全局执行上下文中的this是指向window对象的。
(2) 函数执行上下文
function foo(){
console.log(this);
}
foo();
执行上边这段代码打印出来的也是window,所以默认情况下调用一个函数其执行上下文中的this也是指向window的。
(3) eval执行上下文
eval执行上下文平时用到的比较少,这里就略过了。
根据上边分析,全局上下文中的this、和默认情况调用函数时,函数中的this都是指向window对象,下边我们来看我们是通过什么方式改变this指向的。
2 通过对象调用方法设置
var a = 1
var obj1 = {
a:2,
fn:function(){
console.log(this.a)
}
}
obj1.fn()//2
通过打印结果,我们发现此时的this指向obj1,结论:使用对象来调用其内部的一个方法,该方法的this是指向对象本身的。
var a = 1
var obj1 = {
a:2,
fn:function(){
console.log(this.a)
}
}
var fn2 = obj1.fn
fn2();//1
执行这段代码,会发现this又指向了window。
通过上边两个例子对比,我们可以得出以下结论:
在全局环境中调用一个函数,函数内部的this指向的是全局的window。
通过一个对象来调用其内部的一个方法,该方法执行上下文中的this指向对象本身。
(this永远指向调用它的那个对象。)
3 通过构造函数设置
new一个函数时,背地里会将创建一个连接到prototype成员的新对象,同时this会被绑定到那个新对象上。
function Person(name,age){
// 这里的this都指向实例
this.name = name
this.age = age
this.sayAge = function(){
console.log(this.age)
}
}
var dot = new Person('Dot',2)
dot.sayAge()//2
当new Person()时,js引擎做了以下四件事情:
1 首先创建一个空对象 tempObj;
2 接着用Person.call方法,并将tempObj作为call方法参数;
3 然后执行Person函数,此时的Person函数执行上下文中的this指向了tempObj对象;
4 最后返回tempObj对象
可以用以下代码理解整个调用构造函数的过程:
var tempObj= {}
Person.call(tempObj)
return temObj
4 通过apply、call、bind改变
4.1 applay
applay接收两个参数,第一个是this的值,第二个参数是一个参数数组。当第一个值为null、undefined时,this指向window。
var arr = [1,2,3,89,46]
var max = Math.max.apply(null,arr)//89
4.2 call
call的第一个参数是this的值,后边传入的是一个参数列表。当第一个值为null、undefined时,this指向window。
var arr = [1, 2, 3, 89, 46]
var max = Math.max.call(null, arr[0], arr[1], arr[2], arr[3], arr[4])//89
4.3 bind
和call很相似,第一个参数是this的指向,从第二个参数开始是接收的参数列表。区别在于bind方法返回值是函数以及bind接收的参数列表的使用。
bind返回值是函数
var obj = {
name: 'Dot'
}
function printName() {
console.log(this.name)
}
var dot = printName.bind(obj)
console.log(dot) // function () { … }
dot() // Dot
bind 方法不会立即执行,而是返回一个改变了上下文 this 后的函数。而原函数 printName 中的 this 并没有被改变,依旧指向全局对象 window。
bind参数列表的使用
function fn(a, b, c) {
console.log(a, b, c);
}
var fn1 = fn.bind(null, 'Dot');
fn('A', 'B', 'C'); // A B C
fn1('A', 'B', 'C'); // Dot A B
fn1('B', 'C'); // Dot B C
fn.call(null, 'Dot'); // Dot undefined undefined
call 是把第二个及以后的参数作为 fn 方法的实参传进去,而 fn1 方法的实参实则是在 bind 中参数的基础上再往后排。
5
使用this谨记以下三点:
1 当函数作为对象方法调用时,函数中的this就是该对象;
2 当函数正常调用时,在严格模式下,this值是undefined,非严格模式下this指向的是全局的window;
3 嵌套函数中的this不会继承外层的this值。