JavaScript 因为历史悠久, 所以你可能会遇到经过多人更改过的JavaScript 程式, 里面混杂了不同时期JavaScript 的语法, 导致有时候JavaScript 程式就是难懂, 本文将针对宣告变数的几种方法加以说明, 期望能让大家快速理解其中的差别。
过去最常看到的变数宣告方是就是使用 , 它宣告的变数是函式层级, 也就是只要离开宣告时所在的函式, 这个变数就失效了, 例如: var
function foo () {
var a = 23;
console.log(a);
}
foo () ;
console.log(a);
执行结果如下:
23
Uncaught ReferenceError: a is not defined
由于 a 是在函式 foo 中宣告, 所以叫用 foo 函式时可以取用变数 a , 但是在函式外取用变数 a 就会引发未定义识别字的错误。
如果在函式外使用 var 宣告变数, 它就会变成全域变数, 在程式内任何地方都可以取用, 例如:
var a = 23 ;
function foo () {
console.log(a);
a = 24;
}
foo () ;
console.log(a);
执行结果如下:
你也可以把宣告和设定初值分开来, 不一定要同时完成, 像是这样:
var a;
a = 23 ;
console .log(a);
如果你希望在同一个地方集中宣告变数, 但是在要用到该变数的时候才设定值, 这样的写法就会很有用。
你也可以重复宣告同一个变数, 只要没有设定新的值, 就会保留原值, 例如:
var a = 23 ;
console .log(a);
var a;
console .log(a);
var a = 24 ;
console .log(a);
执行结果如下:
第三行虽然重新宣告 a , 但是没有重新设定值, 所以 a 仍然是23。
变数有一个我其实不知道有什么用途, 但是很多人喜欢拿来考别人的功能, 叫做 , 会把宣告变数的动作提升到执行其他程式前先完成, 意思就是在进入变数的有效范围内时, 会在执行第一行程式前就先宣告变数。因此, 在执行第一行程式的时候, 变数就已经存在了。例如: 變數提升 (variable hoisting)
console .log(a);
var a = 23 ;
console .log(a);
执行结果如下:
undefined
23
由于在执行第一行程式前, 就会先宣告变数, 因此第一行程式并不会引发变数尚未宣告的错误。不过对于以 var 宣告的变数, 变数提升 只会先宣告变数, 并不会执行设定初值的程式, 以上例来说就是不会执行 , 而是设定初值为 , 所以你会看到第一行印出 的值是 。等执行到第二行才会设定变数 的值为23, 因此第三行就会印出23 了。 a = 23undefinedaundefineda
以 var 宣告的全域变数会成为全域物件的属性, 例如:
var a = 23 ;
console .log(globalThis.a);
执行结果如下:
不过这个属性是 不可设定(non-configurable) 的, 也就是不能使用 移除, 例如以下的程式虽然不会发生错误, 但是 却没有作用: delete delete
var a = 23;
delete a;
delete globalThis.a;
console.log(a);
执行结果 a 仍然存在, 印出的值也是正确的:
如果采用严格模式, 就会看到错误讯息:
'use strict' ;
var a = 23 ;
delete globalThis.a;
console .log(a);
执行结果如下:
Uncaught TypeError: property "a" is non-configurable and can 't be deleted
所谓的区块, 就是由一对大括号括起来的区域, 使用 宣告的变数只要出了所在的区块, 就会失效, 例如: let
{
let a = 23 ;
console. log (a);
}
console. log (a);
执行结果如下:
23
Uncaught ReferenceError: a is not defined
由于第二次取用 a 时已经离开了宣告变数的区块, 因此变数 a 已经失效, 就会引发未定义识别字的错误。
在大部分的情况下, 我们很容易辨识区块, 不过在像是 for 的叙述中, 初始设定也是区块的一部份, 因此在初始设定内宣告的变数在 for 结束后也一样会失效, 例如:
for (let i = 0 ; i < 2 ; i ++)
{
console.log(i);
}
console. log ( i );
执行结果如下:
0
1
Uncaught ReferenceError: i is not defined
如果改用 var 宣告变数, 由于并没有离开函式范围, 所以不会引发错误, 例如:
for (var i = 0 ; i < 2 ; i ++)
{
console.log(i);
}
console. log ( i );
执行结果最后会印出回圈结束时的 i 值:
在任何区块外使用 let 建立的变数一样是全域变数, 可在程式中任何地方取用, 例如:
let i = 0 ;
for ( i = 0 ; i < 2 ; i ++) {}
console. log ( i );
结果如下:
以 let 宣告变数也一样具有变数提升功能, 但是并不会设定初值, 在使用变数前一定要先透过 let 宣告, 例如:
console. log (a);
let a = 0 ;
执行时就会引发错误:
Uncaught ReferenceError: can 't access lexical declaration ' a ' before initialization
表示不能在设定初值前就取用已宣告的变数 a 。
以 let 宣告的变数并不会像是以 var 宣告的变数那样成为全域物件的属性, 例如:
let a = 23 ;
console. log (globalThis.a);
执行时印出的并不是 a 的值, 而是 undefined :
undefined
表示全域物件中并没有 a 这个属性。
你也可以使用 宣告变数, 不过这种变数如同 字面所示, 是不能变的, 中文翻译为 常数 。先来看看以下的例子: const const
const a = 23 ;
console. log (a);
a = 24 ;
执行后如下:
23
Uncaught TypeError: invalid assignment to const 'a'
在第三行尝试设定常数内容时就会引发错误, 告诉你不能设定以 const 宣告的常数。
以 const 宣告常数时必须一并设定初值, 不能将宣告与设定初值分开进行, 像是以下的例子就会引发错误:
const a;
a = 23 ;
console. log (a);
执行结果如下:
Uncaught SyntaxError : missing = in const declaration
错误讯息告诉我们在 const 宣告时少了设定初值的 = 。
请特别注意, 不能变更以 const 宣告的常数指的是不能重新设定常数本身, 如果常数的内容是一个物件, 你还是可以变更物件内的属性, 例如:
const a = {name: "John" };
a.name = "Mary" ;
console. log (a);
执行结果如下:
Object { name : "Mary" }
由于变更的是物件的内容, 而不是变更常数 a , 所以可以成功执行。同样的道理, 如果常数的内容是一个阵列, 也可以变更阵列内的项目:
const a = [ 1 , 2 , 3 ];
a.push( 4 );
a[ 0 ] = 10 ;
console. log (a);
执行结果如下:
Array ( 4 ) [ 10, 2, 3, 4 ]
除了不能重新设值外, const 跟 let 是一样的。
JavaScript 是很宽松的, 你甚至会看到有些程式中根本 没有宣告就直接设定变数的值 , 像是这样:
a = 23;
console.log(a);
执行时并不会引发错误, 而且可以正确印出 a 的值:
你甚至还可以随意在函式或是区块直接用同样的方式运作:
function foo () {
a = 23
}
{
b = 24
}
foo ()
console . log (a) ;
console.log(b);
执行结果如下:
你会看到 a 和 b 虽然是在函式以及区块内设定, 可是不像是 var 或是 let 有范围的限制, 两个都变成全域变数那样可以在任何地方使用。
之所以会有前述范例的结果, 是因为当JavaScript 看到识别字时, 会一层层的往外找寻是否有符合该名称的宣告, 例如:
let a = 23
function foo () {
console .log(a)
b = 24 ;
{
c = 25 ;
{
console .log(b)
}
}
}
foo();
执行结果如下:
在 foo 函式中因为没有宣告 a , 所以会往上一层找到全域变数 a ;而最内层区块列印的 b 也是往上一层区块找到的 b 。
如果在全域变数里也找不到, 就会往 全域物件 globalThis 找它的属性, 这也是为什么你可以直接以 alert 叫用定义在 globalThis 物件内的 alert :
alert ( 'call globalThis.alert' );
globalThis .alert ( 'property of globalThis' );
以上两种写法其实是一样的, 当JavaScript 看到 alert 时, 会发现程式中并没有定义 alert 函式, 因此会往全域物件 globalThis 寻找, 发现全域物件有 alert 属性, 因此变成叫用 globalThis.alert 。
在设定值的时候也是一样, 对于没有宣告过的识别字, JavaScript 会将之当成是要设定全域物件的属性, 例如:
a = 23 ;
globalThis.b = 24 ;
console. log (globalThis.a);
console. log (b);
执行结果如下:
第一行要设定 a 时, 会发现程式中没有宣告过 a , 因此实际上执行的是 globalThis.a = 23 , 你可以在第三行看到透过 globalThis.a 取用的就是同一份资料。相同的道理, 第二行虽然是设定 globalThis 的 b 属性, 但是在第四行却可以像是使用变数一样直接以 b 来取得属性值。
你可以在任何地方用这种方式帮全域物件增加属性, 并且以像是全域变数的方式使用该属性。也就是说, 若不使用 var 、 let 、 const 宣告而直接设定值, 并不会建立变数, 而是 设定全域物件 globalThis 的属性 。这样的作法看起来好像很方便, 随时想用就用, 但是却容易造成混淆, 搞不清楚到底是在哪里设定初值, 若要避免这个问题, 可以强制使用 严格模式 , 例如:
'use strict'
a = 23 ;
console .log(a);
执行时就会引发错误:
Uncaught ReferenceError: assignment to undeclared variable a
它会认为你是设值给一个未宣告的变数。
你可能会想到, 前面不是有提到以 var 宣告的全域变数也会变成全域物件的属性, 这样和刚刚提到单纯全域物件的属性不是一样吗?还记得前面说明过, 以 var 宣告的全域变数会成为全域物件中不可设定的属性, 具体的表现就是你无法用 delete 移除它, 但若是纯全域物件的属性, 就可以用 delete 移除, 例如:
globalThis. a = 23
console. log ( a )
delete a
console. log ( a )
执行结果如下:
23
Uncaught ReferenceError: a is not defined
第二次要列印 a 时, 就会因为第三行已经将 a 移除变成未定义的识别字而引发错误。
这样的差异很合理, 因为以 var 宣告的全域变数是真的全域变数, 如果可以删除, 就不再是可以在程式中任何地方取用的全域变数了, 但是全域物件本来就是一个JavaScript 物件, 自然可以随意增删属性。
以上我们就把宣告变数的几种方法介绍完了, 希望有助于厘清为什么这里可以使用这个变数、或者是为什么这个变数变成没有定义的疑惑。简单来说, 为了避免意外, 建议在程式中都只以 let 、 const 宣告, 不要使用 var , 也不要随意帮全域物件新增属性。
本文的目的主要是展示CSS变量是如何工作的。随着Web应用程序变得越来越大,CSS变得越来越大,越来越多,而且很多时候都很乱,在良好的上下文中使用CSS变量,为您提供重用和轻松更改重复出现的CSS属性的机制。
Sass和Less这样的预处理器,让我们的CSS代码保持良好的结构和可维护性。像变量、混合(mixins)、循环控制等特性,增强了动态编写CSS的能力,从而减少重复代码,也加快了我们开发速度。
原生css 中变量的使用,这个重要的 CSS 新功能,所有主要浏览器已经都支持了。本文全面介绍如何使用它,你会发现原生 CSS 从此变得异常强大。声明变量的时候,变量名前面要加两根连词线(--),var()函数用于读取变量。
JavaScript中var、let、const区别?js中let和const都是es5版本新的命名规范,在此之前定定义一个变量只能用var。我们可以把let和const看做是为了弥补var的一些不足而新设计出来的
引擎在读取js代码的过程中,分为两步。第一个步骤是整个js代码的解析读取,第二个步骤是执行。在JS代码执行之前,浏览器的解析器在遇到 var 变量名 和function 整个函数 提升到当前作用域的最前面。
很早直接就了解到CSS变量相关的内容,奈何之前使用价值不高(很多主流浏览器不兼容),最近发现主流浏览器都已经支持了这一变化,CSS变量就像JS的变量,每个类名或者花括号就像一个function,里面的变量只有上下文以内可以获取,这就让CSS有了更多可能性。
var是全局声明,let是块级作用的,只适用于当前代码块;var变量会发生变量提升,let则不会进行变量提升;var 会造成重复赋值,循环里的赋值可能会造成变量泄露至全局
解构赋值官方解释:按照一定的模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。变量的解构赋值就是一种写法,掌握了这种写法可以让我们在书写 javascript 代码时可以更加的简单,迅捷。
JS中的变量是保存在栈内存中的:1.基本数据类型的值直接在栈内存中存储;2.值与值之间是独立存在的,修改一个变量不会影响其他变量;对象是保存到堆内存中的,每创建一个新的对象
这篇文章总结七种办法来交换a和b的变量值 。最最最简单的办法就是使用一个临时变量了 ,最后我的方案是利用了ES6的解构赋值语法 ,它允许我们提取数组和对象的值,对变量进行赋值
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!