1.什么是this
定义:this是包含它的函数作为方法被调用时所属的对象
这句话有些绕,但是别着急,看完下面的文章,我们在回来看这句话
话不多说,看代码
let obj = {
foo: function () {}
};
let foo = obj.foo;
// 写法一
obj.foo()
// 写法二
foo()
上面代码中虽然obj.foo()和foo()指向一个函数,但是执行结果可能不一样,请看下面的例子
let obj = {
foo: function () {
console.log(this.bar)
},
bar: 1
};
let foo = obj.foo;
let bar = 2;
// 写法一
obj.foo() //1
// 写法二
foo() //2
为什么调用同一个函数,输出结果却不一样呢,请继续往下看
结果不一样的原因就是我们在函数内部使用了this关键字
现在我们来分析一下上面的例子
// 写法一
obj.foo() //1
foo运行在obj环境,所以this指向obj
// 写法二
foo() //2
foo运行在全局环境,所以this指向window
网上很多教程会告诉你this指的是当前函数运行时所在的环境,这句
话没错,但是他们通常不告诉你为什么会这样,这篇文章就告诉你js这样
处理的原理,理解了这篇文章,你就会彻底理解this的作用
js之所以有this的设计,跟内存里面的数据结构有关系
2.内存的数据结构
ECMAScript包括两个不同类型的值:基本数据类型和引用数据类型。
1.基本数据类型指的是简单的数据段,
2.引用数据类型指的是有多个值构成的对象。
3.当我们把变量赋值给一个变量时,解析器首先要确认的就是这个值是基本类型值还是引用类型值。
1.基本数据类型
Number、String 、Boolean、Null和Undefined。基本数据类型是按值访问的,
因为可以直接操作保存在变量中的实际值。
示例 :
let a = 10
let b = 'abc'
let c = true
let d = undefined
let e = a
e = 20
console.log(a); // 10值
上面e获取了a的值的拷贝,然后我们给e赋值为20,因为e的值是a的值的一份拷贝,
所以我们打印a的时候,输出的值还是10(这个地方对于初学者来说可能有点绕,
多看几遍,体味一下)
2.引用数据类型
1.也就是对象类型Object type,比如:Object 、Array 、Function 、Data等。
2.javascript的引用数据类型是保存在堆内存中的对象。
3.与其他语言的不同是,你不可以直接访问堆内存空间中的位置和操作堆内存
空间。只能操作对象在栈内存中的引用地址。
let obj = {
a:1,
b:function() {
console.log(123)
}
}
let obj1 = obj
obj.c = '132'
console.log(obj1) //{a:1, b:function(){console.log(123)}, c:'123'}
下图图解
好,看到这里,我想大家对引用数据类型应该有一定的了解了
下面我们就来着重说明一下函数
注意: 函数是一个单独的值,所以它可以在不同的环境(上下文)执行。
我们就拿刚开始的例子来说
let obj = {
foo: function () {
console.log(this.bar)
},
bar: 1
};
可以看成
let obj = {
foo: '函数的引用地址', //这个引用地址指向真的的fun函数
bar: 1
}
函数是一个单独的值,所以它可以在不同的环境(上下文)执行
foo() //单独执行
obj.foo() //执行环境执行
环境变量
JavaScript 允许在函数体内部,引用当前环境的其他变量。
var f = function () {
console.log(x);
};
上面代码中 变量x由运行环境提供
由于函数可以在不同的运行环境执行,所以需要有一种机制,能够在函数体内部获得当前的运行环境(context)。所以,this就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。
var f = function () {
console.log(this.x);
};
let obj = {
foo: function () {
console.log(this.bar)
},
bar: 1
};
let foo1 = obj.foo;
let bar = 2;
// 写法一
obj.foo() //1
// 写法二
foo1() //2
我再来看最开始的这个例子
1.写法一
foo函数是经过obj调用的,是在obj环境运行的,所以this指的是obj环境
2.写法二
先把obj中foo函数的引用交给变量foo1,然后在全局环境下,执行这个
拿到foo函数引用的变量foo1,所以this指的是全局环境
这里需要注意一点:加括号为调用该函数,返回值为函数返回值; 不加括号可认为是查看函数完整信息,即查看整个函数体,返回值即整个函数体
看到这,我们在回头去看本文刚开始的第一句话
this是包含它的函数作为方法被调用时所属的对象
把这句话分成三部分分别代入我们上面的例子中去
1.this是包含它的函数
2.作为方法被调用时
3.所属的对象
参考
阮一峰老师的 《JavaScript 的 this 原理》
结尾
希望大家看了本篇文章都有收获 …
如果文章有什么不对的地方,请斧正,感谢大家
新手一个,大佬勿喷,感谢