this是 JavaScript 语言的一个关键字
它是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用
个人比较喜欢将this理解成上下文语境 既然是语境一定有主语 我们只需要关注 主语是谁就可以了,因为谁用了this 那么this肯定是指向谁的
this的特性
要注意的是,this的语境绝对不是在创建时决定的,而是函数运行是决定的,还是那句话,谁用了this指向谁
列举几个简单的例子容易理解
作为普通函数在全局环境中被调用
var x = 1;
function test() {
console.log(this.x);
}
test(); // 1
这个函数很容易理解,作为一个普通函数在全局中调用 此时this是指向全局 为什么这么说,其实很简单,因为这是我们的简写
var x = 1;
function test() {
console.log(this.x);
}
window.test() // 1
这才是完整的写法,只是我们平时都会省略window,此时我们的方法是通过window使用的,好我们此时主语是window,那么我们就会在window下 寻找x 就找到了全局下的x 输出1,所以我们要知道方法一定是有人调用的,如果没人用那就是window爸爸在用了,所以匿名函数的this一定指向window了
再看一个例子
var x = 1;
function test() {
var y=6
console.log(this.x);
console.log(this.y);
}
window.test(); // 1 undefined
同样的道理,此时y就显示了undefined 此处显示undefined 并不是说没有y,我们都知道var是存在变量提升的,因为js是从上到下解析,如果我们把y放在函数外
var x = 1;
function test() {
console.log(this.x);
console.log(this.y);
}
var y=6
window.test(); // 1 6
此时就能输出6了,因为此时的window.y是等于6的
var x = 1;
function test() {
console.log(this.x);
console.log(this.y);
}
window.test(); // 1
var y=6
此时放在下面又变成undefined了,因为此时的window.y是undefined
在对象中使用例子
var x=2;
function test() {
console.log(this.x);
}
var obj = {};
obj.x = 1;
obj.m = test;
obj.m(); // 1
在对象中设置了俩个属性,一个是x,一个是m,此时obj就变成了
obj={
x:1,
m:function test(){
console.log(this.x)
}
}
此时方法前面有对象了,这个对象是obj,也就是说此时的语境是obj了,那么翻译一下就是obj在使用m方法了,那么this此时是被obj使用的,那么this就指向obj这个对象,也就是说此时this.x==obj.x,很显然打印1
构造函数中使用
所谓构造函数,就是通过这个函数,可以生成一个新对象。这时,this就指这个新对象。
var name='mama';
var age='18';
function test(name,age) {
this.name=name;
this.age=age
}
var obj = new test('this','18');
console.log(name,age) //mama 18
console.log(obj.name,obj.age) //this 18
其实我认为不需要解释了,很容易理解,谁调用此时的this指向谁,就会在谁的下面寻找属性
这里构造函数首字母要大写,不会报错但是是一种规范 额我是故意写这样的
再看一个构造函数的例子
function Person (name) {
console.log(this) // window
this.name = name;
}
Person('inwe')
//使用new
function Person (name) {
this.name = name
console.log(this) //people
that = this
}
var people
console.log(that === people) //false
var people = new Person('iwen')
console.log(that === people) //true
前面两个函数好理解,第二个函数,我们将this赋值给that,看看对比
在构造实例之前,此时函数在全局下,属于window,那自然不等于people
构造实例之后this指向构造的实例,此时this就相当于是people这个实例了
强行改变this语境
使用apply call bind 三个方法强行改变this语境,详情用法可以百度一下,此处只介绍apply
apply()是函数的一个方法,作用是改变函数的调用对象。它的第一个参数就表示改变后的调用这个函数的对象。因此,这时this指的就是这第一个参数
var x = 0;
function test() {
console.log(this.x);
}
var obj = {};
obj.x = 1;
obj.m = test;
obj.m.apply() // 0
obj.m.apply(obj); //1
apply()的参数为空时,默认调用全局对象。虽然是obj调用的方法,但是这时的运行结果为0,证明this指的是全局对象
最后一行又将this指向obj,输出1
从理论以及基础上面来讲 this并不难,谁调用this指向谁,当然还有很多复杂的情况,闭包啊原型链啊,但是万变不离其宗,谁用它就是指向谁,找几个笔试题我们可以分析一下
var name = "caibaojian.com";
var person = {
name: "kang",
pro: {
name: "Michael",
getName: function() {
return this.name;
}
}
};
console.log(person.pro.getName()); // Michael
var pepole = person.pro.getName;
console.log(pepole()); // caibaojian.com
首先我们分析第一个 person.pro.getName()注意此处是有括号的
函数体加()=函数执行
此时相当于返回的就是 this.name
好 谁用this指向谁,方法我们是person下的pro这个对象使用的,name此时就指向pro.name 很简单
分析接下来这个 注意此时是= 在js中=是指右边赋值给左边
此时右边是函数体,它并没有执行,那么此时函数赋值给了people,此时people此时就相当于一个函数
注意了,people前面可是省略了window的 也就是说相当于是window.people(),所以他返回的是全局下的name
'use strict';
var name = "caibaojian.com";
var person = {
name: "kang",
pro: {
name: "Michael",
getName: function() {
return this.name;
}
}
};
console.log(person.pro.getName()); // Michael
var pepole = person.pro.getName;
console.log(pepole()); // undefined
本来是不想复制这个的,其实这里为什么undefined 因为最上面设置了严格模式,而严格模式下没有默认的window全局对象,捎带的提个醒
var name = "caibaojian.com",
person = {
name : "kang",
getName : function(){
return function(){
return this.name;
};
}
};
console.log(person.getName()()); // caibaojian.com
这道题目有点小恶心啊,一步步分析,先看getName()
注意此时它有括号,函数执行返回第一个return 也就是返回一个function
注意 坑来了 此时它又有一个() 又执行了 这其实就相当于一个匿名函数了
一定注意,函数加括号代表执行 匿名函数一定指向window 因为它不需要谁调用 它一打开页面就开始跑了 它已经疯了
function a(xx){
this.x=xx;
return this
};
var x=a(5);
var y=a(6);
console.log(x.x); //undefined
console.log(y.x); //6
这道题可以说是相当的变态,我尽量表达清楚意思
注意了这个函数,它return返回的是this 一个函数的最终结果一定是return
我们要知道,函数改变相应数据结构的同时,并不代表函数结果,只有return 才是函数的结果
那么第一个 var x=a(5) 我们不管发生了什么,我们可以确定此时x已经是window了
同样的道理 var y=a(6) 不管发生了什么 y此时就是window return this返回的就是window
接下来我们逐步分析,var x =window 这个应该没问题
注意 这里是高潮 var y=window 没毛病 但是y执行函数的时候 触发了 this.x=6(这步没看懂的再捋一下)
前面一个var x=a(5)返回的结果是window 就是说this.x=window,执行y的时候对x进行了覆盖
也就是说此时的this.x它是等于6 发现没有
到这里,问题就解决了,返回的最终结果就是console.log(6.x,window.x)
所以答案是undefined 6 是不是很变态
网友评论