var关键字的目的是什么?什么时候应该使用(或省略)?

2020/09/16 12:01 · javascript ·  · 0评论

注意:从ECMAScript版本3或5的角度提出了此问题。随着ECMAScript 6版本中引入新功能,答案可能会过时。

varJavaScript中关键字的功能到底是什么,它们之间有什么区别

var someNumber = 2;
var someFunction = function() { doSomething; }
var someObject = { }
var someObject.someProperty = 5;

someNumber = 2;
someFunction = function() { doSomething; }
someObject = { }
someObject.someProperty = 5;

您什么时候会使用其中一个?为什么/会做什么?

如果您位于全球范围内,则没有太大区别。阅读Kangax的答案以获取解释

如果您在函数中,var则将创建一个局部变量,“ no var”将查找作用域链,直到找到该变量或命中全局作用域为止(此时将创建它):

// These are both globals
var foo = 1;
bar = 2;

function()
{
    var foo = 1; // Local
    bar = 2;     // Global

    // Execute an anonymous function
    (function()
    {
        var wibble = 1; // Local
        foo = 2; // Inherits from scope above (creating a closure)
        moo = 3; // Global
    }())
}

如果您不做作业,则需要使用var

var x; // Declare x

有区别

var x = 1 x在当前范围(即执行上下文)中声明变量如果声明出现在函数中-声明局部变量;如果在全局范围内,则声明一个全局变量。

x = 1另一方面,仅仅是属性分配。它首先尝试解决x范围链问题。如果在范围链中的任何地方找到它,它将执行分配;否则,它将执行分配。如果找不到x,则只有在全局对象(范围链中的顶级对象)创建x属性

现在,请注意,它没有声明全局变量,而是创建了全局属性。

除非您了解变量声明还创建属性(仅在变量对象上),并且Javascript中的每个属性(以及ECMAScript)都有某些描述其属性的标志,否则两者之间的区别可能很小,并且可能令人困惑。不要删除。

由于变量声明使用DontDelete标志创建属性,因此var x = 1x = 1(在全局范围内执行)之间的区别在于前者-变量声明-创建了DontDelete'able属性,而后者则没有。因此,可以从全局对象中删除通过此隐式赋值创建的属性,并且不能删除前一个属性(通过变量声明创建的属性)。

但这当然只是理论,实际上,由于实现中的各种错误(例如来自IE的错误),两者之间甚至存在更多差异

希望这一切有意义:)


[2010年12月16日更新]

在ES5(ECMAScript 5;最近标准化的语言的第5版)中,有一个所谓的“严格模式” —选择加入语言模式,它会稍微改变未声明分配的行为。在严格模式下,分配给未声明的标识符是ReferenceError这样做的理由是抓住意外的任务,防止创建不希望的全局属性。一些较新的浏览器已经开始对严格模式进行滚动支持。参见,例如,我的compat表

说这是“ 本地”和“ 全球之间的差异并不完全准确。

最好将其视为“ 本地”和“ 最近之间的差异最接近的肯定是全局的,但情况并非总是如此。

/* global scope */
var local = true;
var global = true;

function outer() {
    /* local scope */
    var local = true;
    var global = false;

    /* nearest scope = outer */
    local = !global;

    function inner() {
        /* nearest scope = outer */
        local = false;
        global = false;

        /* nearest scope = undefined */
        /* defaults to defining a global */
        public = global;
    }
}

在浏览器中执行Javascript时,所有代码都被with语句包围,如下所示:

with (window) {
    //Your code
}

有关更多信息with-MDN

由于在当前范围内var声明了变量,因此在内部窗口中声明与完全不声明之间没有区别var

当您不直接在窗口内部(例如在函数内部或在块内部)时,就会出现区别。

使用var可以隐藏具有相同名称的外部变量。这样,您可以模拟“私有”变量,但这是另一个主题。

经验法则是始终使用var,因为否则会冒引入细微错误的风险。

编辑:在收到我的批评之后,我想强调以下几点:

  • var在当前范围内声明一个变量
  • 全局范围是 window
  • 在全局范围内不使用var隐式声明var(窗口)
  • 在全局范围(窗口)中使用声明变量var与省略变量相同。
  • 声明在使用窗口不同的范围的变量var 是不一样的东西作为声明的变量,而不var
  • 始终var明确声明,因为这是一个好习惯

始终使用var关键字声明变量。为什么?良好的编码习惯本身就足够了,但是省略它意味着它是在全局范围内声明的(这样的变量称为“隐式”全局变量)。道格拉斯·克罗克福德(Douglas Crockford)建议不要使用隐式全局变量,并且根据Apple JavaScript编码指南

没有var
关键字创建的
任何变量都在全局范围内创建,并且在函数返回时不会被垃圾回收(因为它不会超出范围),这会导致内存泄漏。

这是一个很好的示例,说明了如何通过不声明局部变量而陷入困境var

<script>
one();

function one()
{
    for (i = 0;i < 10;i++)
    {
        two();
        alert(i);
    }
}

function two()
{
    i = 1;
}
</script>

i在循环的每次迭代中重置,因为它不是在for循环中本地声明,而是在全局中声明)最终导致无限循环

我会说最好var在大多数情况下使用

局部变量总是比全局范围内的变量快。

如果不使用var声明变量,则该变量将处于全局范围内。

有关更多信息,您可以在Google中搜索“范围链JavaScript”。

不要使用var

var是ES6之前的变量声明方法。我们现在就在将来,您应该这样编码。

使用constlet

const应该用于95%的情况。这样一来,变量引用就不会更改,因此数组,对象和DOM节点属性可以更改,并且应该更改为const

let应该用于期望重新分配的任何变量。这包括在for循环中。如果您写的内容varName =超出初始化范围,请使用let

正如大多数其他语言所期望的,两者都具有块级作用域。

另一个区别,例如

var a = a || [] ; // works 

a = a || [] ; // a is undefined error.

使用var始终是一个好主意,以防止变量造成全局范围混乱和变量彼此冲突,从而导致不必要的覆盖。

没有var-全局变量。

强烈建议始终使用use var语句,因为在局部上下文中初始化全局变量是有害的。但是,如果您需要这个肮脏的把戏,则应在页面开始处写评论:

/* global: varname1, varname2... */

这是我为您编写的示例代码,用于理解此概念:

var foo = 5; 
bar = 2;     
fooba = 3;

// Execute an anonymous function
(function() {    
    bar = 100;             //overwrites global scope bar
    var foo = 4;           //a new foo variable is created in this' function's scope
    var fooba = 900;       //same as above
    document.write(foo);   //prints 4
    document.write(bar);   //prints 100
    document.write(fooba); //prints 900
})();

document.write('<br/>');
document.write('<br/>');
document.write(foo);       //prints 5
document.write(bar);       //prints 100
document.write(fooba);     //prints 3

@Chris S给出了一个很好的示例,展示了varno与no 之间的实际差异(和危险)var这是另一种,我发现这特别危险,因为差异仅在异步环境中可见,因此在测试过程中很容易漏掉。

如您所料,以下代码段输出["text"]

function var_fun() {
  let array = []
  array.push('text')
  return array
}

console.log(var_fun())

以下代码段也是如此(请注意let之前缺少的内容array):

function var_fun() {
  array = []
  array.push('text')
  return array
}

console.log(var_fun())

异步执行数据操作仍然使用单个执行程序产生相同的结果:

function var_fun() {
  array = [];
  return new Promise(resolve => resolve()).then(() => {
    array.push('text')
    return array
  })
}

var_fun().then(result => {console.log(result)})

但是在多个行为上却有所不同:

function var_fun() {
  array = [];
  return new Promise(resolve => resolve()).then(() => {
    array.push('text')
    return array
  })
}

[1,2,3].forEach(i => {
  var_fun().then(result => {console.log(result)})
})

但是使用let:

function var_fun() {
  let array = [];
  return new Promise(resolve => resolve()).then(() => {
    array.push('text')
    return array
  })
}

[1,2,3].forEach(i => {
  var_fun().then(result => {console.log(result)})
})

当有人试图学习这一点时,这就是我的看法。对于初学者来说,以上示例可能有点过于复杂。

如果运行此代码:

var local = true;
var global = true;


function test(){
  var local = false;
  var global = false;
  console.log(local)
  console.log(global)
}

test();

console.log(local);
console.log(global);

输出将显示为:false,false,true,true

因为它认为函数中的变量与函数外的变量是分开的,所以使用术语局部变量,这是因为我们在赋值中使用了var。如果删除函数中的var,则它现在如下所示:

var local = true;
var global = true;


function test(){
  local = false;
  global = false;
  console.log(local)
  console.log(global)
}

test();

console.log(local);
console.log(global);

输出为false,false,false,false

这是因为与其在局部作用域或函数中创建新变量,不如使用全局变量并将它们重新分配为false。

我看到人们在声明带或不带var以及函数内部或外部的变量时感到困惑这是一个深入的示例,将引导您完成这些步骤:

在jsfiddle上查看下面的脚本

a = 1;// Defined outside the function without var
var b = 1;// Defined outside the function with var
alert("Starting outside of all functions... \n \n a, b defined but c, d not defined yet: \n a:" + a + "\n b:" + b + "\n \n (If I try to show the value of the undefined c or d, console.log would throw 'Uncaught ReferenceError: c is not defined' error and script would stop running!)");

function testVar1(){
    c = 1;// Defined inside the function without var
    var d = 1;// Defined inside the function with var
    alert("Now inside the 1. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);

    a = a + 5;
    b = b + 5;
    c = c + 5;
    d = d + 5;

    alert("After added values inside the 1. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);
};


testVar1();
alert("Run the 1. function again...");
testVar1();

function testVar2(){
    var d = 1;// Defined inside the function with var
    alert("Now inside the 2. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);

    a = a + 5;
    b = b + 5;
    c = c + 5;
    d = d + 5;

    alert("After added values inside the 2. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);
};

testVar2();

alert("Now outside of all functions... \n \n Final Values: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n You will not be able to see d here because then the value is requested, console.log would throw error 'Uncaught ReferenceError: d is not defined' and script would stop. \n ");
alert("**************\n Conclusion \n ************** \n \n 1. No matter declared with or without var (like a, b) if they get their value outside the function, they will preserve their value and also any other values that are added inside various functions through the script are preserved.\n 2. If the variable is declared without var inside a function (like c), it will act like the previous rule, it will preserve its value across all functions from now on. Either it got its first value in function testVar1() it still preserves the value and get additional value in function testVar2() \n 3. If the variable is declared with var inside a function only (like d in testVar1 or testVar2) it will will be undefined whenever the function ends. So it will be temporary variable in a function.");
alert("Now check console.log for the error when value d is requested next:");
alert(d);

结论

  1. 无论使用var声明还是不使用var声明(如a,b),如果它们的值超出函数范围,它们都将保留其值,并且还将保留通过脚本添加到各种函数内部的任何其他值。
  2. 如果在函数内部(例如c)中声明了不带var的变量,它将像以前的规则一样工作,从现在开始,它将在所有函数中保留其值。它要么在函数testVar1()中获得了第一个值,要么仍然保留该值,并在函数testVar2()中获得了附加值。
  3. 如果仅在函数内部使用var声明变量(例如testVar1或testVar2中的d),则在函数结束时它将是未定义的。因此它将是函数中的临时变量。

在代码内部,如果您使用变量而不使用var,那么会发生的是自动将var var_name放置在全局范围内,例如:

someFunction() {
    var a = some_value; /*a has local scope and it cannot be accessed when this
    function is not active*/
    b = a; /*here it places "var b" at top of script i.e. gives b global scope or
    uses already defined global variable b */
}

除范围问题外,有些人还提到了吊装,但没有人举任何例子。这是全球范围的一种:

console.log(noErrorCase);
var noErrorCase = "you will reach that point";

console.log(runTimeError);
runTimeError = "you won't reach that point";

不使用“ var”变量只能在设置值时定义。例如:

my_var;

无法在全球范围任何其他范围内工作它应该具有如下值:

my_var = "value";

另一方面,您可以定义可变的like;

var my_var;

它的值是undefined(它的值不是,null并且null有趣地不等于。)。

除非打算在浏览器中将变量附加到窗口对象,否则应使用var关键字。这是一个链接,它解释了作用域以及使用和wihtout var关键字进行的glocal作用域和局部作用域之间的区别。

当在不使用var关键字的情况下定义变量时,看起来就像是一个简单的“赋值”操作。

当将值分配给javascript中的变量时,解释器首先尝试在与赋值相同的上下文/作用域中查找“变量声明”。解释器执行时dummyVariable = 20,它将在函数开始处查找dummyVariable的声明。(由于所有的变量声明都由javascript解释器移动到上下文的开头,因此称为提升)

您可能还想看看javascript中的吊装

本文地址:http://javascript.askforanswer.com/varguanjianzidemudeshishenmeshenmeshihouyinggaishiyonghuoshenglue.html
文章标签: ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!