感谢阮一峰老师:http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html

涉及到的知识点:变量提升

定义:

  1. 哪个对象调用函数,函数里面的this指向哪个对象。
  2. this默认指向window(全局)。
  3. 函数里面也有一个this。 
  4. this在函数执行时才能确定指向谁。
  5. 闭包中的内函数this默认指向window。
  6. DOM元素中的事件(onclick、onmousedown等等) this指向这个DOM元素对象。

情景1:

var x = 0;

function test() {

	this.x = 2;
	alert(window.x)
}

test()

解释:

这里实际上是window调用了test()方法,所以this指的就是window。实际上,上面的代码可以转变为:

var x = 0;

var test = function() { //转换函数

	this.x = 2;
	alert(window.x)
}

test()

由于test函数在声明时没有在某函数内部声明,所以test函数在用var定义时,属于window对象,再转变一下:

window.x = 0;//因为var定义时,作用域就是window

window.test = function() {

	this.x = 2;
	alert(window.x)
}

window.test()

这样就清晰了:哪个对象调用函数,函数里面的this指向哪个对象。明显这里是window调用了test方法。

这里有一个知识点需要声明下:在ES5中,若变量没有用var去声明时,默认属于window对象,即以下两个定义是等价:

x = 0; <===>  window.x = 0;
 test1 = function(){
 	console.log('1')
 }
 window.test1 = function(){
 	console.log('1')
 } 

情景2:

function test() {
  console.log(this.x);
}

var obj = {};
obj.x = 1;
obj.m = test;

obj.m();  

以上代码输出什么?

首先:代码我们先转换一下(一步步来)

第一步,修改函数的表现形式:

var test = function() {
  console.log(this.x);
}

var obj = {};
obj.x = 1;
obj.m = test;

obj.m(); // 1

第二步,将obj定义的变量提升:

var obj = {};
obj.x = 1;

var test = function() {
  console.log(this.x);
}
obj.m = test;

obj.m(); // 1

第三步,obj.m 等价于test函数的右边的function,把test定义去掉,function函数给obj.m:

var obj = {};
obj.x = 1;

obj.m = function() {
  console.log(this.x);
}

obj.m(); // 1

调用,显然,调用函数的是obj ,所以this就表示obj,而obj定义了x为1 ,所以输出结果为 1。

情景3:

function test() {
 this.x = 1;
}

var obj = new test();
console.log(obj.x) // 1

运行结果为1。为了表明这时this不属于window(全局)对象,我们对代码做一些改变:

var x = 2;
function test() {
  this.x = 1;
}

var obj = new test();
console.log(x)  // 2

这里我建议一步步来,先进行转换:

window.x = 2;
var test=function() {
  this.x = 1;
}

var obj = new test();
console.log(x)  // 2

再转:

window.x = 2;
window.test = function() {
  this.x = 1;
}

window.obj = new test();

console.log(window.x)  // 2 表明全局变量x的值根本没变。

test();//当执行test方法时,实际上是执行了:window.test();执行此函数时,x的值已经改变
console.log(window.x)  // 1 这里的x的值,被this.x这一行所改变

所以:哪个对象调用函数,函数里面的this指向哪个对象。

情景4:apply 调用

apply定义:应用某一对象的一个方法,用另一个对象替换当前对象。 //说实话这样不太能理解 

看以下代码:

var x = 0;
function test() {
 console.log(this.x);
}

var obj = {};
obj.x = 1;
obj.m = test;
obj.m.apply() // 0

首页进行变量提升、代码转换,以上代码等价于:

window.x = 0;
window.obj = {};
obj.x = 1;

obj.m = function() {
 console.log(this.x);
}
obj.m.apply() // 0

apply()的参数为空时,默认调用window(全局)对象。

 好,继续转换:

window.x = 0;
window.obj = {};
obj.x = 1;

obj.m = function() {
 console.log(this.x);
}
obj.m.apply(window) // 0

上面的代码输出为0,我们可以这样理解:

第一步:首先我们不要apply,有了上面的基础我们知道,输出的是1。

window.x = 0;
window.obj = {};
obj.x = 1;

obj.m = function() {
 console.log(this.x);
}
obj.m() // 1

第二步:我们加上apply,但是定义说了,如果apply没有参数,默认参数是window(全局)对象,好,我们加上。

这里可见区别在哪,就是多了一个apply,这5个字母,就把函数内的this指给了window(原本是指向obj,因为是obj调用了m函数)。

window.x = 0;
window.obj = {};
obj.x = 1;

obj.m = function() {
 console.log(this.x);
}
obj.m.apply(window) // 实际上和obj.m.apply()等价

 第三步:这次我们把apply的参数改一下,把m函数内的this指向obj本身,应该怎么做?没错,就是把obj放进去替换window(全局)对象:

window.x = 0;
window.obj = {};
obj.x = 1;

obj.m = function() {
 console.log(this.x);
}
obj.m.apply(obj) // 输出1 

情景5: 匿名函数

定义:在函数表达式中,创建一个函数并将它赋值给一个变量,若此时function关键字后没有标识符,那么创建的函数可称为匿名函数:

var a=function(){ return 1 };

1. 无论在何种情况下,匿名函数中的this永远指向的是window。

2.前提是不要放到window.onload,window.ready 函数下,否则this的指向就会发生变化。

情景6: 闭包的指向

https://www.bbsmax.com/A/gAJG9g00dZ/ 

10-26 21:17