1. 普通函数中
var name = 'globalName';
var obj = {
name: 'objName',
fn: function() {
console.log('current name is:', this.name);
}
}
obj.fn();//objName
var innerFn = obj.fn;
innerFn();//globalName,浏览器和NodeJS不一样
- 一般情况下最后是谁调用的函数(并且此函数和this直接相关),this指向谁
- obj.fn()中,调用fn的是obj对象,所以this指向obj对象,得到的是obj.name
- innerFn(),没有调用方,默认为window调用(浏览器中)
1.1 立即执行函数模式
var name = 'globalName';
var obj = {
name: 'objName',
fn: function() {
function gn() {
console.log('current name is:', this.name);
}
gn();
}
}
obj.fn();//globalName
- 最终【执行】的函数是gn,而调用gn的是window(因为没有调用方),此模式类似执行回调函数
1.2 返回函数模式
var name = 'globalName';
var obj = {
name: 'objName',
fn: function() {
return function gn() {
console.log('current name is:', this.name);
}
}
}
obj.fn()();//globalName
2. 构造函数中
var name = "globalName";
function Test(name) {
console.log("current this is: ", this); //Test函数构造的实例testObj
console.log(this instanceof Test);//true
this.name = name;
}
var testObj = new Test("Lawson");
console.log(testObj.name);//Lawson
- 构造函数中(用new调用函数),this指向生成的实例
var name = "globalName";
function Test(name) {
this.name = name;
return {
name: 'Nion'
};//构造函数中返回了非基本类型
}
var testObj = new Test("Lawson");
console.log(testObj.name);//Nion
var name = "globalName";
function Test(name) {
this.name = name;
return 0;//基本类型
}
var testObj = new Test("Lawson");
console.log(testObj.name);//Lawson
var name = "globalName";
function Test(name) {
this.name = name;
return this;
}
var testObj = new Test("Lawson");
console.log(testObj.name);//Lawson
- 若构造函数中返回了非【基本类型】(number string boolean null undefined symbol bigint)也不是this,则生成的实例会被非基本类型替换
3. 结合call apply bind函数
call 传送门
apply 传送门
bind 传送门
- 三者的第一个参数,都会改变执行函数中this指向
- call后面接收的参数,以正常参数一样,一个个传入,最后执行函数
- apply后面接收一个参数,将所有的正常参数,按照类数组的方式传入,最后执行函数
- bind的入参和call一样,但是最后不执行函数,而是返回被改变this之后的新函数,传入的参数会作为新函数的预置参数,从而实现偏函数的功效
var name = 'globalName';
var obj = {
name: 'objName',
fn: function() {
console.log('current name is:', this.name);
}
}
//和obj.fn()效果一致,而且使用call更加不容易混淆this
obj.fn.call(obj);//objName
//和var innerFn = obj.fn; innerFn(); 效果一致
obj.fn.call(window);//globalName
//注意:call后面的参数,可以传入null 即obj.fn.call(null)实现软绑,但是严格模式下报错
4. 箭头函数
下面只谈和this相关的内容
4.1 立即执行函数模式
var name = 'globalName';
var obj = {
name: 'objName',
fn: function() {
console.log('this.name of fn is:', this.name);
var arrowFn = () => {
console.log('current name is:', this.name);
}
arrowFn();
}
}
obj.fn();
//current name is: objName
//this.name of fn is: objName
4.2 返回函数模式
var name = 'globalName';
var obj = {
name: 'objName',
fn: function() {
console.log('this.name of fn is:', this.name);
return () => {
console.log('current name is:', this.name);
}
}
}
obj.fn()();
//this.name of fn is: objName
//current name is: objName
var arrowFn = obj.fn();
arrowFn();
//this.name of fn is: objName
//current name is: objName
var innerFn = obj.fn;
innerFn()();
//this.name of fn is: globalName
//current name is: globalName
obj.fn().call(window);
//this.name of fn is: objName
//current name is: objName
- 对象中没有函数级作用域
var name = 'globalName';
var obj = {
name: 'objName',
methods: {
showName: () =>{
console.log('current name is:', this.name);
}
}
}
obj.methods.showName();//globalName
- JS中说作用域,一般是按照函数级作用域进行分级的
- 箭头函数的this,在声明的时候已经和其父级作用域(函数级)绑定,无法解绑,bind call apply均不能改变其this指向