用文字记录生活,留下美好瞬间
原创

JavaScript中的this

共 3,564 字,需阅读 9 分钟
2018/09/07 上午
993 次阅读

this 表示当前对象的一个引用,在JavaScript中,this会随着执行环境的改变而改变。实际上 this的最终指向的是那个调用它的对象

一般 this 的指向有这几种情况:

  • 单独使用,this 指向全局对象
  • 非严格模式下,函数中的 this 指向全局对象
  • 严格模式下,函数中的简单调用,this 是 undfined
  • 在函数内部,this 的指向在函数定义的时候是不能确定的,只有函数执行的时候才能确定
  • 在方法中,this 指代该调用方法的对象

想要理解this,你可以先记住以下两点:

  1. this永远指向一个对象;
  2. this的指向完全取决于函数调用的位置;
          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
function fun(){ console.log(this.name, arguments); } ​ var obj = { name:'Superficial Blog', f:fun } ​ var name = 'Superficial'; ​ obj.f(); // Superficial Blog fun(); // Superficial

#apply

概念: 调用一个具有给定 this 值的函数,以及以一个数组(或一个类数组对象)的形式提供的参数

语法:

          
  • 1
function.apply(thisArg, [arg1, arg2, ...])

还是使用上面的例子:

          
  • 1
  • 2
  • 3
fun.apply(obj, [1,2,3,4,5]) // Superficial Blog // Arguments(3) [1, 2, 3, 4, 5, callee: ƒ, Symbol(Symbol.iterator): ƒ]

#call

概念: 使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数

语法:

          
  • 1
function.call(thisArg, arg1, arg2, ...)

参数

  • thisArg:可选。在 function 函数运行时使用的 this 值,请注意,this可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 null 或者 undefined 时会自动替换为指向全局对象,原始值会被包装
  • arg1, arg2, ...:指定的参数列表
          
  • 1
  • 2
  • 3
  • 4
function fn() { console.log(this, arguments) } fn() // window

这里直接执行 fn 函数相当于执行的 window.fn ,this 指向的是 window 对象

接下来我们使用 call 改变 this 指向

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
fn.call() // window fn.call(null) // window fn.call(undefined) // window fn.call("Superficial") // Superficial fn.call("Superficial", 2018, 08, 12) // String {"Superficial"} // Arguments(3) [2021, 4, 12, callee: ƒ, Symbol(Symbol.iterator): ƒ]

当我们使用 call 不传递参数时,或者传递的第一个参数为 null 、undefined 时函数还是指向 window,传递的参数列表从第二个参数开始

#bind

概念:创建一个新的函数,在 bind 被调用时,这个新函数的 this 被指定为 bind 的第一个参数,而其余参数将作为新函数的参数,供调用时使用

语法:

          
  • 1
function.bind(thisArg[, arg1[, arg2[, ...]]])

参数

  • thisArg:调用绑定函数时作为 this 参数传递给目标函数的值。

  • arg1, arg2, ...:当目标函数被调用时,被预置入绑定函数的参数列表中的参数

返回值

返回一个原函数的拷贝,并拥有指定的 this 值和初始参数

看了上面 bind 的概念,我们发现 bind 有返回值,并且返回的是原函数的拷贝,也就是说像上面使用 call 或者 apply 那样使用,bind 并不会执行

还是上面那个例子

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
function fn() { console.log(this, arguments) } const fn1 = fn.bind("Superficial") fn1() // Superficial

注意: 该方法的语法和作用与 apply 方法类似,只有一个区别,就是 call 方法接收一个参数列表,而 apply 方法接收的是一个包含多个参数的数组

看完上面的应该对这三个方法已经懂了,那么接下来,我要放大招了

实现 apply 方法

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
Function.prototype.apply = function(ctx) { const ctx = ctx || window // 将当前被调用的方法定义在 ctx._fn 上(为了能以对象调用的方式绑定this) ctx._fn = this // 以对象调用的方式调用 _fn,此时 this 指向 ctx ,也就是传入的需要绑定的this指向 const res = arguments[1] ? ctx._fn(...arguments[1]) : ctx._fn() // 删除该方法,不然会对传入对象造成污染 delete ctx._fn return res }

实现 call 方法

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
Function.prototype.call = function (ctx) { const ctx = ctx || window // 将当前被调用的方法定义在 ctx._fn 上(为了能以对象调用的方式绑定this) ctx._fn = this // 获取实参 const args = Array.from(arguments).slice(1) // 以对象调用的方式调用 _fn,此时 this 指向 ctx ,也就是传入的需要绑定的this指向 const res = arguments.length > 1 ? ctx._fn(...args) : ctx._fn() // 删除该方法,不然会对传入对象造成污染 delete ctx._fn return res }

实现 bind 方法

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
// ES6 Function.prototype.bind = function(ctx) { const ctx = ctx || window ctx._fn = this // 获取实参 const args = Array.from(arguments).slice(1) return (...arg2) => { let allArgs = args.concat(arg2) return allArgs.length > 0 ? ctx._fn(...allArgs) : ctx._fn() } }

你明白了嘛?

自由转载 - 署名 - 非商业性使用
https://zhangwurui.cn/article/23
0/0条看法
访客身份
在下有一拙见,不知...
期待你的捷足先登