怎么在javascript中灵活运用 this
this 是什么
Javascriptthis关键词指的是他所属的对象,它拥有不同的值,具体取决于使用的位置和调用方式。
- 使用方式在方法中,它指向这个方法的拥有者在函数中,它是全局对象window严格模式下在函数中,它是undefined单独使用时,它是全局对象window在事件中,它指向触发事件的目标对象e.target
不同执行模式下的差异化
javascript 中的this不同于其他编程语言,在严格模式和非严格模式下, 它的值是不同的,下面举个例子。
// 非严格模式 function foo() { return this } console.log(foo() === window.foo()) //true // 严格模式 ;('use strict') function foo() { return this } console.log(foo()) // undefined console.log(window.foo()) // window
非严格模式下foo不论是函数调用还是作为一个方法调用,内部this的指向都是window。 在严格模式下,foo作为一个函数调用时this的值为undefined,而当做window对象的一个方法调用时,它的值指向了调用它的window对象。从代码书写的语义化来看的话,这种this的指向会更合理,这也是javascript的执行环境逐渐向严格模式靠拢的原因,从语言层面抛除一些不符合预期的执行结果。
灵活使用this手动实现函数的call和apply
了解了this的诸多特性后我们能利用它实现什么有趣的功能呢?没错,就是下面要手动实现函数的call和apply方法。
首先我们需要知道es5的call方法实现了什么功能,它的第一个参数是调用函数的this绑定,其余的参数会作为实参传递给执行的函数。了解了这个功能,我们就可以动手去实现它了。
Function.prototype._call = function _call(context, ...args) { if (context == undefined) { context = window || global } else { context = Object(context) } // 获取当前要调用的函数挂载到`context`上 context.handler = this const result = context.handler(...args) delete context.handler return result } // 测试一下 const value = 10 const foo = { value: 1, } function print(arg) { console.log(this.value) return arg } const retVal = print._call(foo, 2) // 1 console.log(retVal) // 2
为了让_call函数的第一个参数作为this传入到执行函数中去,这里在_call函数内部做了一个变通,把待执行的函数作为context对象的一个方法调用,这样就实现了更改函数调用时this指向的问题。测试后的执行结果也是符合我们的预期的。同理apply函数的实现方式也是如此,只需要把传递的参数处理一下即可,这里就不再演示了。