资讯专栏INFORMATION COLUMN

this的五种不同情形

Hydrogen / 424人阅读

摘要:的五种不同情形默认情况在默认的,纯粹的函数调用时,视作全局性调用,此时的指向全局对象,在浏览器环境下,也即对象。构造函数当一个函数被当做构造函数,用关键字新建一个对象的时候,这个函数内部的以及原型链上的都会指向这个新建的对象。

this的五种不同情形 默认情况

在默认的,纯粹的函数调用时,视作全局性调用,此时的this指向全局对象Global,在浏览器环境下,也即window对象。

</>复制代码

  1. window.x = "Jackie"
  2. function func() {
  3. console.log(this.x)
  4. }
  5. func() // Jackie

在严格模式("use strict")下,会禁止this指向全局对象,此时的this会是undefined

作为对象的方法调用

此时this指向调用这个方法的对象。

</>复制代码

  1. var x = "Property of Window"
  2. var obj = {}
  3. obj.x = "Property of obj"
  4. obj.f = function () {
  5. console.log(this.x)
  6. }
  7. obj.f() // Property of obj
  8. // 值得注意的情况
  9. var f = obj.f
  10. f() // Property of Window
callapplybind 的显式绑定

callapplybind都可以改变一个函数的this指向。

callapply

callapply会将它们的调用对象的this指向它们的第一个参数。

</>复制代码

  1. function f () {
  2. console.log(this.x)
  3. }
  4. var x = "Property of Window"
  5. var obj = {
  6. x: "Property of obj"
  7. }
  8. f.apply(obj) // "Property of obj"

当传入的第一个参数为undefined,或者不传入参数时,在非严格模式下,自动会将this指向全局对象Global,在浏览器里是window对象,严格模式下则会是undefined

</>复制代码

  1. function f () {
  2. console.log(this)
  3. }
  4. f.apply() // window
  5. f.apply(undefined) // window
  6. function ff () {
  7. "use strict"
  8. console.log(this)
  9. }
  10. ff.apply() // undefined
  11. ff.apply(undefined) // undefined

callapply没有本质区别。唯一的区别在于:

</>复制代码

  1. call()方法接受的是若干个参数的列表,而apply()方法接受的是一个包含多个参数的数组

bind

bind和前面两者也并未有什么本质的区别,只不过bind将第一个参数绑定当调用函数的this上,并将这个函数返回(不执行)。

</>复制代码

  1. function f () {
  2. console.log(this.x)
  3. }
  4. var x = "Property of Window"
  5. var obj = {
  6. x: "Property of obj"
  7. }
  8. var ff = f.bind(obj)
  9. ff() // "Property of obj"
构造函数

当一个函数被当做构造函数,用new关键字新建一个对象的时候,这个函数内部的this以及原型链上的this都会指向这个新建的对象。

</>复制代码

  1. function Jackie(para) {
  2. this.para = para
  3. console.log(this)
  4. }
  5. Jackie.prototype.log = function(){
  6. console.log(this)
  7. }
  8. Jackie("hehe") // Window
  9. var p = new Jackie("haha") // Jackie {para: "haha"}
  10. p.log() // Jackie {para: "haha"}
其他值得注意的绑定 放在超时代码里

JavaScript中超时调用的代码都是在全局作用域中执行的,因此函数中this的值会指向window对象,在严格模式下也一样。因为超时调用的代码都会有一个隐式绑定:setTimeout(f, time) == setTimeout(f.bind(window), time)

</>复制代码

  1. "use stric"
  2. var x = "Property of Window"
  3. var obj = {}
  4. obj.x = "Property of obj"
  5. obj.ff = function () {
  6. setTimeout(
  7. function () {
  8. console.log(this.x)
  9. }, 100)
  10. }
  11. obj.ff() // Property of Window
  12. // 可以这么解决问题
  13. obj.fff = function () {
  14. var that = this
  15. setTimeout(
  16. function () {
  17. console.log(that.x)
  18. }, 100)
  19. }
  20. obj.fff() // Property of obj
事件监听函数中的this

事件监听函数中的this指向监听对象。

</>复制代码

  1. var one = document.getElementById("one")
  2. one.onclick = function () {
  3. console.log(this)
  4. };
  5. one.click() //
箭头函数

箭头函数中this的指向,在函数定义时即绑定完毕,且后续无法更改。

</>复制代码

  1. var obj = {
  2. x: 1
  3. }
  4. var f1 = () => {
  5. console.log(this)
  6. }
  7. f1.apply(obj) // Window
  8. var f2 = function () {
  9. var f3 = () => {
  10. console.log(this)
  11. }
  12. return f3
  13. }
  14. var f4 = f2.apply(obj)
  15. f4() // Object {x: 1}

一个更神奇的例子,超时调用的代码在定义时,绑定了this的指向。

</>复制代码

  1. function foo() {
  2. setTimeout(() => {
  3. console.log("id:", this.id);
  4. }, 100);
  5. }
  6. var id = 21;
  7. foo.call({ id: 42 }); // id: 42
绑定的优先级

</>复制代码

  1. var obj = {x: 0, name: "obj"}
  2. var robj = {x: -1, name: "robj"}
  3. var factory = function (x) {
  4. this.x = x
  5. console.log(this)
  6. }
  7. var factoryBind = factory.bind(obj)
  8. robj.factory = factoryBind
  9. robj.factory(2) // Object {x: 2, name: "obj"},作为方法的绑定的优先级低于bind的显式绑定
  10. factoryBind.call(robj, 3) // Object {x: 3, name: "obj"},call的优先级低于bind
  11. console.log(robj) // Object {x: -1, name: "robj", factory: function},未对robj进行修改
  12. console.log(obj) // Object {x: 3, name: "obj"},修改的是obj,因为this指针指向未变化
  13. var p = new factoryBind(4) // factory {x: 4}
  14. console.log(p) // factory {x: 4}
  15. console.log(obj) // Object {x: 3, name: "obj"},构造函数绑定的优先级高于bind的显式绑定

可以见得,优先级从高到低:

new,构造绑定

bind,显式绑定

call/apply,显示绑定

作为方法绑定

默认绑定

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/84404.html

相关文章

  • this五种指法

    摘要:中只有的作用域是动态作用域的五种绑定初学时,会想当然认为遵循某一条规律,就像物理学那样,然而并不是。的绑定分为五种情况,这五种情况之间毫无规律可言。以至指向更加扑朔迷离。 this 到底指向哪里 以下如果没提及,则为严格模式。 js中作用域有两种: 词法作用域 动态作用域 词法作用域 词法作用域指在书写代码时就被确定的作用域。看如下代码 var value = 1; ...

    Caizhenhao 评论0 收藏0
  • React Native 传参五种方式

    摘要:在中由于业务的需要我们往往要在诸多的页面间,组件之间做一些参数的传递与管理在这里我总结了几大经过验证,稳定好用的方式给大家导航传值推荐指数适用范围相邻页面间传值兼容性原理为页面的上挂载了对象可用来做路由跳转,在做页面跳转时可以携带参数回调方 在React Native 中由于业务的需要, 我们往往要在诸多的页面间,组件之间做一些参数的传递与管理, 在这里我总结了几大经过验证,稳定好用的...

    cnTomato 评论0 收藏0
  • 实现compose五种思路

    好久没有更新了,最近学习的过程中一直在用联想的思维来去看问题,javascript是一门非常灵活的语言,集合了好多语言的特性和多种编程模式,对于compose的实现,就有非常多的思路,每一种思路都有自己的特点,实现之后,有种殊途同归的快感。下面就是我总结的实现compose函数的五种思路。 面向过程 函数组合(reduce) 函数交织(AOP编程) Promise(sequence) Gener...

    RayKr 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<