this
关键字是一个非常重要的语法点。毫不夸张地说,不理解它的含义,大部分开发任务都无法完成。
简单说,this
就是属性或方法“当前”所在的对象。
那么我们来看看this指向的规则如下:
1. 在全局作用域下,this指向window;this和window的空间地址是一样的;
2. 给元素的事件行为绑定方法,那么方法中的this指向被绑定这个元素;
3. 函数体中的this看函数执行前有没有".",如果有点,点前面是谁,this就是谁,如果没有点,那么this指向window;
4. 自执行函数中的this永远指向window;
5. 回调函数中的this指向window;
6. 构造函数中的this指向实例
7. call、apply、bind可以改变this的指向;
有了以上的规则,在理解起来相对要容易很多了。那么 this 实质到底是什么呢?
JavaScript 语言之所以有 this 的设计,跟内存里面的数据结构有关系。
var obj = { foo: 5 };
上面的代码将一个对象赋值给变量obj
。JavaScript 引擎会先在内存里面,生成一个对象{ foo: 5 }
,然后把这个对象的内存地址赋值给变量obj
。也就是说,变量obj
是一个地址(reference)。后面如果要读取obj.foo
,引擎先从obj
拿到内存地址,然后再从该地址读出原始的对象,返回它的foo
属性。
现在问题就来了,由于函数可以在不同的运行环境执行,所以需要有一种机制,能够在函数体内部获得当前的运行环境(context)。所以,this
就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。
var f = function () {
console.log(this.x);
}
var x = 1;
var obj = {
f: f,
x: 2,
};
// 单独执行
f() // 1
// obj 环境执行
obj.f() // 2
上面代码中,函数f
在全局环境执行,this.x
指向全局环境的x
;在obj
环境执行,this.x
指向obj.x
。
//第1题
var a = 2; //2 3 4
var obj1 = {
a: 1, //3
fn1: (function (a) {
//3 4 5
this.a = a;
a++;
return function () {
this.a = a++;
console.log(a);
}
})(a)
};
obj1.fn1(); //4
var fn1 = obj1.fn1;
fn1(); //5
console.log(a); //4
console.log(obj1.a); //3
//说明:
1.obj1 在赋值时,自执行函数会执行,形参私有作用域 var a 会被存储起来
//第2题
var c = 3; //2 3 4
function getC() {
this.c++;
return function (c) {
c = this.c * 2;
console.log(c);
}
}
var obj3 = {
c: 2, //3
getC: (function () {
this.c -= 1;
return this.getC
})()
};
getC();
obj3.getC();
var f3 = obj3.getC;
f3();
console.log(window.c); //4
console.log(obj3.c); //3
//第3题
function g1() {
this.g = "gg"
}
var obj4 = {
g1:function () {
this.g = "gg"
},
gg: function () {
//this -->obj4
//但是没加this 所以下个作用域是全局window
g1();
}
};
obj4.g1(); //给 obj4 添加键值对 {g:"gg"}
obj4.gg(); //给 window 添加属性
console.log(obj4); //{g: "gg", g1: ƒ, gg: ƒ}
console.log("g" in window); //true
//第4题
var number = 2; //4 8
var obj = {
number: 4, //8
//自执行函数执行
fn1: (function () {
//var number //3 9 27
this.number *= 2;
number = number * 2;
var number = 3;
return function () {
this.number *= 2;
number *= 3;
alert(number);
}
})()
};
var fn1 = obj.fn1;
alert(number); //4
fn1(); //9
obj.fn1(); //27
alert(window.number); //8
alert(obj.number); //8
//第5题
var num = 2; //4 6
var obj = {num: 1}; //3
obj.fn = (function (num) {
//var num //1 0 1 0 1
this.num += 2;
num--;
return function (n) {
this.num += 2;
num--;
console.log(n + ++num);
}
})(this.num);
var fn = obj.fn;
fn(2); //3
obj.fn(1); //2
console.log(num, obj.num); //6 3
//第6题
var i = 10;
function a() {
i = 20;
console.log(i); //20
for (var i = 0; i < 6; i++) {
console.log(i);
//0
//1
//2
//3
//4
//5
}
console.log(this.i); //10
console.log(i); //6
}
//第7题
function test() {
b();
var a = 1;
function b() {
console.log(1);
console.log(a);
var a = 2;
}
}
test(); //undefined
//第8题
var i = 10;
function a() {
i = 20;
console.log(i);
for (i = 0; i < 6; i++) {
console.log(i);
}
console.log(this.i);
console.log(i);
}
a();
//20
//0
//1
//2
//3
//4
//5
//6
//6
console.log(i); //6
//第9题
function test() {
console.log(b);
var b = 1;
//这里被覆盖了不在是函数了
b();
function b() {
console.log(1);
console.log(a);
}
}
test();
//Uncaught TypeError: b is not a function