js this相关问题总结

应用场景

  1. 作为普通函数
  2. 使用callapplybind
  3. 作为对象方法被调用
  4. class方法中被调用
  5. 箭头函数

使用要领

this在各场景下取什么值,是在函数执行的时候确定的,不是在函数定义的时候确定的!!


下面介绍this在各个场景中的使用:

1. 普通函数

function fn1() {
    console.log(this); 
};
fn1(); // window

this指向window,这里调用fn1函数的作用域是全局作用域

2. 使用call,apply,bind

callapplybind的作用都是为了改变函数的this指向。

  • call

第一个例子是关于this指向的:

window.color = 'red';
document.color = 'yellow';
var s1 = { color:  'blue' };
function changeColor() {
    console.log(this.color);
}

// 以下注释中的“=>”是指向的意思~
changeColor.call(); // red (不传就是默认 changeColor为全局函数,this => 全局)
changeColor.call(window); // red (this => 全局)
changeColor.call(document); // yellow (this => document)
changeColor.call(this); // red (this => 全局作用域)
changeColor.call(s1); // blue (this => s1这个对象)

第二个例子是关于传参的:

var obj = {
    name: '夏洛'
}
function func(age, grade) {
    console.log(`${age}岁的${this.name}上${grade}年级`);
}
func.call(obj, '20', '五'); // '20岁的夏洛上五年级'
func.call(obj, '20'); // '20岁的夏洛上undefined年级'
func.call('20', '五'); // '五岁的undefined上undefined年级'
// 第一个参数永远是你要指向的对象

参数多传了人家函数也不接收,少传或者不传人家找不到这个值,就会报undefined

总结:
对于一个函数:

var func = function(arg1, arg2) {}

我们就酱调用:

func.call(this, arg1, arg2)

其中,this是你想要指定的上下文对象(就是你想要指定this的区域),arg1arg2是你传递的参数。

  • apply

apply和call一样,第一个例子就省略啦
下面看apply的传值:

var obj = {
    name: '夏洛'
}
function func(age, grade) {
    console.log(`${age}岁的${this.name}上${grade}年级`);
}
func.apply(obj, ['20', '五']); // '20岁的夏洛上五年级'
func.call(obj, ['20']); // '20岁的夏洛上undefined年级'
func.call(['20', '五']); // 'undefined岁的undefined上undefined年级'
func.call(obj); // 'VM2914:5 undefined岁的夏洛上undefined年级'

有人说,我参数不写成数组行不行?
那指定不行,而且会报这个错:
Uncaught TypeError: CreateListFromArrayLike called on non-object

总结:
applycall一样,只不过二者在传参的时候形式不一样
apply是数组形式,call是参数列表(直接传就完事)
所以,对于一个函数:

var func = function(arg1, arg2) {};

我们就酱调用:

func.apply(this, [arg1, arg2]);
  • bind

其实,bind和call是很相似的,也可以改变函数体内this的指向,只不过call直接就调用了,而bind返回的是一个函数,需要我们再调用一下就好啦

下面的是bind的例子:

function fn1() {
    console.log(this); 
};
const fn2 = fn1.bind({ x: 200 })
fn2(); // { x: 200 }

总结:
对于一个函数:

var func = function(arg1, arg2) {};

我们就酱调用:

func.bind(this, arg1, arg2)(); // 注意这里我们要调用一次

3. 对象方法调用

看一个不那么普通的🌰:

const xialuo = {
    name: '夏洛'
    love() {
        console.log(`${this.name}喜欢秋雅`); // this 指当前对象xialuo
    },
    wait() {
        setTimeout(function() {
            console.log(`${this.name}等马冬梅一起回家`); // this 指window
        })
    }
}

xialuo.love()的中的this指的就是xialuo,这没有问题
xialuo.wait()的中的this就不是指的xialuo这个对象了,因为setTimeout这个函数调用的时候和this的第一个情况(当做普通函数执行)是一样的,也就是说,这个函数执行是setTimeout本身触发的执行,它不是xialuo.love这种方式触发的。

4. 箭头函数调用

🌰:(还是夏洛)

const xialuo = {
    name: '夏洛'
    love() {
        console.log(`${this.name}喜欢秋雅`); // this 指当前对象xialuo
    },
    wait() {
        setTimeout(() => {
            console.log(`${this.name}等马冬梅一起回家`); // this 指当前对象
        })
    }
}

ps:箭头函数的this永远取它上级作用域的this!!!它自己本身不会决定this的值。

5. class
class People {
    constructor(name) {
        this.name = name;
        this.age = 20;
    }
    sayHi() {
        console.log(this);
    }
}
const xialuo = new People('夏洛');
xialuo.sayHi(); // xialuo 对象
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容