2019年3月9日 中雨 14°C~17°C
广州持续下来很久很久的雨,一个星期?两个星期?忘了,又加上回南天,衣服不干,emmmm...
一、this的用法
this是函数运行时,在函数体内自动生成的一个对象,只有在函数体内部使用。
function test(){
this.x = 1;
}
//函数test运行时,内部会自动生成一个this对象可以使用
函数的不同使用场合,this有不同的值。总的来说,this是函数运行时所在的环境对象
this的用法
1. 纯粹的函数调用
全局调用,函数最常用的方法,此时this代表全局对象。
var x = 1;
function test(){
console.log(this.x);
}
test(); //1
2.作为对象的调用方法
函数可以作为对象的方法来被调用,此时this指向这个对象。
function test(){
console.log(this.x)
}
var obj = {};
obj.x = 1;
obj.m = test;
obj.m(); //1
3.作为构造函数调用
通过构造函数,可以生成一个新的对象。这是,this指向这个新的对象。
var x = 2;
function test(){
this.x = 1;
}
var obj = new test();
x // 2
obj.x //1;
4. apply调用
apply()是函数的一个方法,作用是改变函数的调用对象,它的第一个函数就表示改变后调用这个函数的对象。此时this指的就是这第一个参数。
var x = 0;
function test() {
console.log(this.x);
}
var obj = {};
obj.x = 1;
obj.m = test;
obj.m.apply(); //0
apply()的参数为空时,默认调用全局对象,因此,运行结果为0,this指向全局对象。
如果:
obj.m.apply(obj); //1
运行结果变成了1,this指向对象obj;
二、this的原理
1. 由来
var obj = {
foo: function() { console.log(this.bar)},
bar: 1
}
var foo = obj.foo;
var bar = 2;
//写法一
obj.foo(); // 1
//写法二
foo(); // 2
**this指的是函数运行时所在的环境,对于obj.foo,foo运行在obj环境,所以this指向obj,对于foo()来说,foo运行在全局环境,所以this指向全局环境。
函数的运行环境是怎么决定的?
2. 内存的数据结构
var obj = { foo: 5};
上面代码将一个对象赋值给变量obj,①JavaScript引擎会先在内存里面生成一个对象{ foo: 5},② 然后把这个对象的内存地址赋值给变量obj。
所以,变量obj是一个地址,如果要读取obj.foo,引擎会先从obj拿到内存地址,然后再从该地址读出原始的对象,返回它的foo属性。
原始的对象以字典结构保存,每一个属性名称都对应一个属性描写对象。如上例子foo属性,实际上是以下面的形式保存:
{
foo: {
[[value]]: 5
[[writable]]: true
[[enumerable]]: true
[[configurable]]: true
}
}
foo属性的值保存在属性貌似对象的value属性里面。
3. 函数
上面讲到对象的属性的值是一个值,二属性的值也可能是一个函数。
var obj = { foo: 5};
var obj = { foo: function(){} };
这时,引擎会将函数单独保存在内存中,然后再将函数的地址赋值给foo属性的value属性。
其实思路和上面的一样,只不过多了一个步骤:①引擎会将函数单独保存在内存中,②然后在内存里生成一个对象,对象的foo属性的value值是函数的内存地址,③将对象赋值给obj
var f = function() {};
var obj = {f : f};
f(); //单独执行
obj.f(); //obj环境执行
4. 环境变量
在函数体内部,可以引用当前环境的其他变量
var f = function() {
console.log(x);
}
//函数体的变量x,由运行环境提供
由于函数可以在不同的运行环境中执行,this被设计于在函数体内部,指代函数当前的运行环境(context)。
var f = function() {
console.log(this.x);
}
//this.x 指当前运行环境的x
var f = function() {
console.log(this.x);
}
var x = 1;
var obj = {
f: f,
x: 2
}
f() // 1, f()在全局环境执行
obj.f() //2
三、this的指向形式(4种)
(1)一般函数,this指向全局对象window;
(2)在严格模式下“use strict”,为undefined;
(3)对象的方法里调用,指向该方法的对象;
(4)构造函数里的this,指向创建出来的实例
四、改变this的指向形式
.call()
call(thisScope,arg1,arg2,arg3...)
thisScope为新的指向
.apply()
.apply(thisScope,[arg1,arg2,arg3...])
两个参数,thisScope为新的指向
bind()
bind(thisScope,arg1,arg2,arg3...)
改变this的指向,返回的是函数,还需调用,而call()和apply()是改变this的指向并执行调用该函数
2019年3月8日 小雨
准备换工作之际,在几乎毫无准备的情况下,去面试了一家公司,面试官提到了怎样改变this的指向,我答不出。
于是去翻了阮一峰大神的博客,
JavaScript的this用法http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html
JavaScript的this原理http://www.ruanyifeng.com/blog/2018/06/javascript-this.html
还有看了一篇简洁的总结
https://www.jianshu.com/p/c415530030a9