资讯专栏INFORMATION COLUMN

JavaScript:万恶的this拿命来(一)

loostudy / 2292人阅读

摘要:在脚本中,默认指向一个空对象,并不是指向,也不是指向。举个栗子,在函数执行后,覆盖原先的值我们在外部定义了一个名为的全局变量,它会被默认添加到全局的属性上。总结在不同的执行环境中的默认指代通过省略声明变量导致变量提升现象的发生及预防

侃侃JavaScript中的this
  

this为何如此多变?

this总是跟它的执行上下文有关,而在JavaScript总会有开辟新的执行上下文的东西,比如函数,所以,this才如此的变化。
  

执行环境对JavaScript中的this有影响吗?

JavaScript是一门解释型语言,需要有一个执行环境去执行它,通常的执行环境是浏览器,还有node脚本,还有`REPL`(“读取-求值-输出”循环(Read-Eval-Print Loop,简称REPL))。

如果对REPL有兴趣的话,博客中的另一篇文章介绍了`REPL`
  

this默认指代谁?

在不同的执行环境中,会指代不同的对象

浏览器中:

> this              // Window {top: Window, window: Window,...
> this === window   //true

> var a = 1;        //在全局中,用var声明变量,会默认给window添加
> this.a   // 1
> window.a // 1
> b = 1;            //不使用var声明变量,会默认给全局的this添加属性
> this.b   // 1
> window.b // 1

node脚本中

console.log(this);              //{}
console.log(this === global);   //false
console.log(this === window);   //ReferenceError: window is not defined

var a = 1;         //在全局中,使用var声明变量,未给global添加属性

console.log(this.a);            //undefined
console.log(global.a);          //undefined
console.log(window.a);          //ReferenceError: window is not defined

b = 1;            //不使用var声明变量,会默认给全局的global添加属性。

console.log(this.b);            //undefined
console.log(global.b);          // 1   

在node脚本中,this默认指向一个空对象,并不是指向global,也不是指向window。

REPL

> this
{ DTRACE_NET_SERVER_CONNECTION: [Function],
  DTRACE_NET_STREAM_END: [Function],
  ...
> global === this  //true

> var a = 1;       //在全局中,使用var声明变量,会默认给全局的global添加属性
> this.a           // 1
> global.a         // 1

> b = 1;           //不使用var声明变量,会默认给全局的this添加属性
> this.b           // 1 
> global.b         // 1
实例扩展
  

我们对于省略var的变量声明方式,我们总说它是不安全的,但是是合法的。

为什么不安全?

如上文所述:不使用var声明变量,会让变量默认的添加到了全局的this中,这有时候会莫名的给变量提升它的作用域,从而影响其他全局变量。

举个栗子:

var position = "outer";           //this.position = "outer"

function test(){
    position = "inner";           //this.position = "inner",在函数执行后,覆盖原先的值
    console.log(this.position);
}

test();

我们在外部定义了一个名为position的全局变量,它会被默认添加到全局this的属性上。

然后在我们的test函数中,又定义了一个同名的变量,但是注意,函数中的变量声明没有用var

因为我们并没有对函数实例化,所以this.positionthis会默认指代全局。

而当我们调用函数test时,函数会生成一个执行上下文,而内部position会将作用域从函数内部提升到全局,从而覆盖(污染)了外部全局定义的position变量。

所以,在JavaScript的严格模式中,是不允许省略var来声明变量的。故在声明变量的时候,就顺手加上var吧。

总结

this在不同的执行环境中的默认指代

通过省略var声明变量导致“变量提升”现象的发生及预防

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

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

相关文章

  • JavaScript:万恶this命来(二)

    摘要:构造函数对于被实例化的,我们称之为构造函数,及使用关键字调用的,对于它们来说,会被改变,指向实例。上栗子全局赋上属性通过关键字创建实例,改变函数内部指向注解通过这个栗子,我们可以看出,通过创建构造函数的实例,使得的指向改变,指向了实例本身。 用栗子说this Bug年年有,今年特别多 对于JavaScript这么灵活的语言来说,少了this怎么活! function ...

    fox_soyoung 评论0 收藏0
  • JavaScript:万恶 this 命来(三)

    摘要:闭包执行上下文决定了变量作用域而闭包,它其实是一种决策,是一种模式,让我们可以灵活的改变变量作用域。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。只要咱们弄明白闭包,其中的自然跑不掉。 闭包 this 执行上下文决定了变量作用域 而闭包,它其实是一种决策,是一种模式,让我们可以灵活的改变变量作用域。 按惯例,上栗子 var global = glo...

    Cympros 评论0 收藏0
  • 异步流程控制:7 行代码学会 co 模块

    摘要:而在中是迭代器生成器,被创造性的拿来做异步流程控制了。当执行的时候,并不执行函数体,而是返回一个迭代器。行代码再看看文章开头的行代码首先生成一个迭代器,然后执行一遍,得到的是一个对象,里面再执行。 广告招人:阿里巴巴招前端,在这里你可以享受大公司的福利和技术体系,也有小团队的挑战和成长空间。联系: qingguang.meiqg at alibaba-inc.com 首先请原谅我的标题...

    tinna 评论0 收藏0
  • 不用 Spring Security 可否?试试这个小而美安全框架

    摘要:写在前面在一款应用的整个生命周期,我们都会谈及该应用的数据安全问题。用户的合法性与数据的可见性是数据安全中非常重要的一部分。 写在前面 在一款应用的整个生命周期,我们都会谈及该应用的数据安全问题。用户的合法性与数据的可见性是数据安全中非常重要的一部分。但是,一方面,不同的应用对于数据的合法性和可见性要求的维度与粒度都有所区别;另一方面,以当前微服务、多服务的架构方式,如何共享Sessi...

    toddmark 评论0 收藏0
  • JavaScript面试系列:JavaScript设计模式之桥接模式和懒加载

    摘要:桥接模式的核心在于将抽象部分和它的实现部分分离,使它们都可以独立的变化。看起来这个版本已经很完美了不,它仍然有可以优化的空间,即题目提到的桥接模式。使用桥接模式的实现版本这个实现包含了三个函数。这个例子体现了桥接模式的作用。 我写的程序员面试系列文章 Java面试系列-webapp文件夹和WebContent文件夹的区别? 程序员面试系列:Spring MVC能响应HTTP请求的原因?...

    tracymac7 评论0 收藏0

发表评论

0条评论

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