JavaScript中,this指向的问题 | 掘金·日新计划

60 阅读3分钟

前言

相信很多人在撸代码的时候,涉及到this总会出现一些问题,无法得到我们想要的值。大多数时候是我们没有弄清楚this的指向到底是什么,所以在某些情况下,this得到的不是我们想要的值。最近学习了一下函数中this指向的问题,在此分享出来也方便自己日后巩固学习。

谁调用就指向谁

一般情况下,谁调用,就指向谁,没有任何对象调用时,默认指向window对象

function fun() {
    console.log(this);
}
fun() // Window {window: Window, self: Window, document: document, name: '', location: Location, …}

以上代码中,this就指向了window。

函数fun相当于挂在window上,调用fun()等同于调用window.fun(),可以看作fun()是被window调用,因此this指向window.

扩展:self在函数中同样返回window,self是window的另一种写法

另外四种情况下

1、全局作用域或者普通函数中

function fun() {
    console.log(this);
}
fun(); // window
setTimeout(function () {
    console.log(this); // window
}, 1000)

以上代码中,this指向全局对象window(注意:定时器里面的this指向window)。

2、对象的方法调用中

var obj = {
    say: function () {
        console.log(this);
    }
}
obj.say() // {say: ƒ}

以上代码中,谁调用,this就指向谁。

3、事件处理程序中

<button>按钮</button>
<script>
    var btn = document.querySelector('button')
    btn.onclick = function () {
        console.log(this); // <button>按钮</button>
        fun()
    }
    function fun() {
        console.log(this); // window
    }
</script>

以上代码中,this指向被操作的元素对象,也有可能会指向window。

4、构造函数中this指向构造函数的实例

function Person(name, age) {
    this.name = name;
    this.age = age;
    this.show = function () {
        console.log(this);
    }
}
// 利用构造函数Person创建了两个实例化对象
var p1 = new Person('aaa', 12)
var p2 = new Person('ddd', 14)
p1.show() // Person {name: 'aaa', age: 12, show: ƒ}
p2.show() // Person {name: 'ddd', age: 14, show: ƒ}

以上代码中,this指向构造函数的实例。

改变this指向方法(函数的标准调用)

call()

  • 语法:fun.call(this指向,函数参数)。
  • 第一个参数是this指向,第二个参数开始都是函数的实参。
  • 立即执行。
function fun(value) {
    console.log(this); // String {'aaa'}
    console.log(value); // bbb
}
fun.call('aaa', 'bbb')

apply()

  • 语法:fun.apply(this指向,函数参数)。
  • 第一个参数是this指向,第二个参数必须数组
  • 立即执行。
function fun(value) {
    console.log(this); // String {'aaa'}
    console.log(value); // bbb
}
fun.apply('aaa', ['bbb'])

bind()

  • 语法:fun.bind(this指向,函数参数)(函数参数)。
  • 第一个参数是this指向,第二个参数开始都是函数的实参。
  • 不是立即执行,需要手动调用。
function fun(value) {
    console.log(this); // String {'aaa'}
    console.log(value); // bbb
}
fun.bind('aaa', 'bbb')()

小结

  1. 全局作用域下指向window,定时器指向window。
  2. 对象中,谁调用就指向谁。
  3. 事件处理程序中,指向事件处理程序绑定的元素。
  4. call、apply 是立即执行的,bind 需要手动进行调用。
  5. call、bind 第二个参数开始都是函数的实参,apply 第二个必须是一个数组。

扩展:

  • 接收多个实参可以用伪数组arguments。
  • 在es6语法中,接收实参可以用...FnName,同时...可以将数组里的值分隔开来。

好啦,今天的知识就分享到这里啦。欢迎大家在评论里指点讨论。