首先要认清几个概念:
- 普通函数的调用方式
- 构造函数的调用方式
- 全局对象
在ES5之前,构造函数和普通函数的定义方式都是一样的:function 函数名(){}
,只不过构造函数名约定好是大写字母开头...
-
普通函数 的调用不用多说了吧。就是
函数名字()
-
构造函数 的调用,可以通过关键字
new
出来 对象的,就是new 函数名字()
- 全局对象: 在web端,全局对象是window;在node端,全局对象是global
- 函数的最后,如果没有写return,默认 return this
关键点来了
- 普通函数的调用
function demo() {
console.log(this);
}
demo(); // this 指向 全局对象
- 构造函数的调用
function Demo() {
console.log(this);
}
new Demo(); // this 指向 Demo
这里判断就是:调用函数的时候有没有new
关键字。
- 如果有
new
,说明这是构造函数在构造一个对象。而this
指向的是new
出来的这个对象; - 如果没有
new
,并且只是普通函数自己调用,this
指向的是全局。
如果普通函数被别人调用?
var obj = {
fn:function(){
console.log(this);
}
}
obj.fn(); // this 指向 obj
此时,fn这个函数算是被obj调用(因为fn执行之前有个小数点,这个小数点紧挨着的前面是谁,就算是被谁调用)
你学废了吗?
来一个稍微绕一点的。
var girl = {
friend: {
fn: function(){
console.log(this); //window
}
}
}
var boy = girl.friend.fn; // 注意哦,这里并没有人要执行。看到有小括号才算执行:(),这里只是赋值操作
boy();
还是那句话,boy执行的时候:
- 先判断有没有
new
- 判断前面没有小数点
所以this
指向全局
再来
var girl = {}
function fn() {
console.log(this);
}
girl.fn = new fn(); // this 指向 fn
console.log(girl.fn); // this 指向 fn
已经有new
了,就不要关心前面的小数点了。
小结:
- 调用的时候有
new
,this
指向该对象。 - 调用的时候前面有小数点,
this
指向小数点前面紧挨着的那个对象
如果有了return:
function Demo() {
console.log(this);
return 123;
}
var res = new Demo(); // 此时函数已经执行了。this 指向 Demo。
console.log(res); // 此时 this 依然指向 Demo
function Demo() {
console.log(this);
return {
name: '李华'
};
}
const res = new Demo(); // 此时函数已经执行了。this 指向 Demo。
console.log(res); // 此时,res 中的 this 指向 返回的对象
小结,如果函数最后有return:
- 如果
return
的是基本数据类型,接受者的this
指向跟之前说的一样。 - 如果
return
的是引用类型,接受者的this
指向return
的这个数据。
注意一些情况啊:
function Demo() {
console.log(this)
this.skill = function () {
console.log(this)
return {};
}
}
var res = new Demo().skill;
res(); // this 指向全局
虽然有new
关键字,但看清楚,不是把 new 出来的这个对象交给 res,而是这个对象里面的方法。
PS:
- 严格模式下,函数自己调用,this 指向 undefined,不再指向 window 了
- ES6中有个叫做 箭头函数
=>
,它本身是不存在this
的,它里面的this
,取决于外层给它的
网友评论