资讯专栏INFORMATION COLUMN

[Javascript实验课] What is this?

RyanHoo / 769人阅读

摘要:实验一全局下的全局作用域下的函数里面的,显然等于全局对象所以,显然,可以通过,改变里面的全局变量所以,如果你创建了一个构造函数,然后不小心调用了它,那么相当于你为全局对象赋值了,这个缺陷可以通过里面的来解决。

javascript 中的关键词 this 代指 执行上下文(Execution Contexts),函数作用域中的this,理解上来说是指调用这个函数的对象。相信以下几个实验可以加深对this关键字的理解。

实验一:全局下的this

全局作用域下的函数里面的this,显然等于全局对象window

function test(){
  console.log(this === window) //true
}
test()

所以,显然,可以通过this,改变window里面的全局变量

var global = "global"

function test(){

  this.global = "global2"

}
test()
console.log(global)//global2

所以,如果你创建了一个构造函数,然后不小心调用了它,那么相当于你为全局对象赋值了,这个缺陷可以通过ES5里面的"use strict"来解决。

"use strict";

var global = "global"

function test(){
  console.log(this)//undefined
  this.global = "global2"//TypeError because "this" undefined

}
test();

严格模式下,全局模式下的函数内部的this为undefined,而不会默认为window

实验二 : 对象中的this

通过普通对象声明的函数this

var myobject = {
  foo : function(){
    console.dir(this) //myobject
  }
}
myobject.foo()

foo里面的this指向调用foo的对象myobject,这个对象里面只有一个方法foo,因此我们可以通过this操作 指向对象 里的其他值

var myobject = {
  v : 5,
  foo :  function(){
        this.v ++
        console.log(this.v)//6
   } 
}

myobject.foo()

多层对象的情况下,this指向最近的一个对象,即谁直接调用这个函数,谁是this

var myobject = {
  foo : {
    bar : function(){
        console.dir(this)//foo
    }
  }

}
myobject.foo.bar()

以上情况this指向foo对象,那么我们再考虑如下的情况

var myobject = {
  foo : function(){
    console.dir(this)//myobject
    var bar = function(){
      console.dir(this)/*window "use strict" undefined*/
    }
    bar()
  }
}
myobject.foo()

我们可以发现,如果在foo函数里声明新的函数(闭包),比如绑定事件,settimeout里的匿名函数等情况,这里面的this会变为window(严格模式下undefined)。
造成这个错误的原因是,bar()调用的时候,是全局对象window在调用的它,而不是通过myobject调用(换句话说myobject里面压根就没有bar),这种情况下如果要通过myobject调用bar需要用到call或apply

var myobject = {
  foo : function(){
    console.log(this)//myobject
    var bar = function(){
      console.log(this)
    }   

    bar.call(myobject)//myobject
  }

}
myobject.foo()

理解为,函数中的this,跟调用时的情形有关。

构造函数通过new来赋值情形也跟对象类似,比如

function testobject(){
  this.kk = 6;
  this.dd = function(){console.log(this)};
}

var fish = new testobject
fish.dd();

/*
[object Object] {
  dd: function (){window.runnerWindow.proxyConsole.log(this)},
  kk: 6
}
*/

new操作符会将this指向构造函数构造出来的对象

实验三:事件回调里的this
var myobject = {
  foo : function(){
    console.log(this)//myobject

    document.body.onclick = function(){
      console.dir(this)//[object HTMLBodyElement]
    }
  }
}
myobject.foo()

点击回调里的this指向点击对象

总结:解决办法

为避免this混乱,可以采用下面几种方法

通过变量传递
var myobject = {
  foo : function(){
    var that = this   
    document.body.onclick = function(){
      console.dir(that)//myobject
    }
  }
}
myobject.foo()
通过call或apply
var myobject = {
  foo : function(){
    var bar = function(){
      console.log(this)
    }   

    bar.call(myobject)//myobject
  }

}
myobject.foo()
直接用对象名代替this
var myobject = {
  v : 5,
  foo : function(){
    var bar = function(){
      console.log(++myobject.v)//直接修改myobject对象里的值
    }   
    bar();
  }

}
myobject.foo()
更多相关请参考

http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html

http://javascript.ruanyifeng.com/oop/basic.html

https://developer.mozilla.org/zh-CN/docs/JavaScript/Reference/Operators/this#Function_context_.E5.87.BD.E6.95.B0.E4.B8.8A.E4.B8.8B.E6.96.87

http://ryanmorr.com/understanding-scope-and-context-in-javascript/

http://stackoverflow.com/questions/9468055/what-does-new-in-javascript-do-anyway

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

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

相关文章

  • ECMASCript 2019可能会有哪些特性?

    摘要:可能不会包括所有的语法提案。事实上,有些提案已经被搁置很多年了。因此,很可能也会在今年月份发布。 译者按: 又过了1年... 原文:Whats New in JavaScript for 2019 译者: Fundebug 为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。 最近这些年,ECMASCript标准发展节奏非常稳定,每年都会发布新的特...

    tuantuan 评论0 收藏0
  • [译] 前端攻略-从路人甲到英雄无敌二:JavaScript 与不断演化的框架

    摘要:一般来说,声明式编程关注于发生了啥,而命令式则同时关注与咋发生的。声明式编程可以较好地解决这个问题,刚才提到的比较麻烦的元素选择这个动作可以交托给框架或者库区处理,这样就能让开发者专注于发生了啥,这里推荐一波与。 本文翻译自FreeCodeCamp的from-zero-to-front-end-hero-part。 继续译者的废话,这篇文章是前端攻略-从路人甲到英雄无敌的下半部分,在...

    roadtogeek 评论0 收藏0
  • JavaScript选择题解答(1-20)

    摘要:最近做了个上的的测试题目地址,错了一大堆,感觉的概念还有很多不是很清晰,这里记录一下个人博客文章地址第一题解答这里考的是的用法。如果出现的数字不符合后面输入的进制,则为,所以第二个值为。 最近做了个heroku上的JavaScript的测试(题目地址),错了一大堆,感觉js的概念还有很多不是很清晰,这里记录一下 个人博客文章地址 第一题 What is the result of...

    Worktile 评论0 收藏0
  • Learning Notes - Understanding the Weird Parts of

    摘要:标签前端作者更多文章个人网站 Learning Notes - Understanding the Weird Parts of JavaScript 标签 : 前端 JavaScript [TOC] The learning notes of the MOOC JavaScript: Understanding the Weird Parts on Udemy,including...

    inapt 评论0 收藏0
  • JavaScript Getters and Setters

    For the most part, in JavaScript, what you see is what you get. A value’s a value; there are no tricks. Sometimes however, you want a value that’s based on some other values: someone’s full name, for ...

    warnerwu 评论0 收藏0

发表评论

0条评论

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