摘要:聲明的變量聲明可以在包含它的函數(shù),模塊,命名空間或全局作用域內(nèi)部任何位置被訪(fǎng)問(wèn)。但是塊級(jí)作用域變量需要在明顯不同的塊里聲明。會(huì)輸出與預(yù)料一致的結(jié)果聲明聲明是聲明變量的另一種方式。
從var聲明說(shuō)起
一直以來(lái)我們都是通過(guò)var關(guān)鍵字定義JavaScript變量。
var a = 10;
var聲明的變量var聲明可以在包含它的函數(shù),模塊,命名空間或全局作用域內(nèi)部任何位置被訪(fǎng)問(wèn)。
比如在其它函數(shù)內(nèi)部訪(fǎng)問(wèn)相同的變量:
function f() { var a = 10; return function g() { var b = a + 1; return b; } } var g = f(); g(); // returns 11;
這些作用域規(guī)則可能會(huì)引發(fā)一些錯(cuò)誤。
第1個(gè)問(wèn)題就是多次聲明同一個(gè)變量并不會(huì)報(bào)錯(cuò)。比如下面這個(gè)例子:
function sumMatrix(matrix: number[][]) { var sum = 0; for (var i = 0; i < matrix.length; i++) { var currentRow = matrix[i]; for (var i = 0; i < currentRow.length; i++) { sum += currentRow[i]; } } return sum; } sumMatrix([[1,2],[3,4]])
一般認(rèn)為,運(yùn)行的結(jié)果應(yīng)該為10。但結(jié)果并非如此,因?yàn)樗衖都引用相同的函數(shù)作用域內(nèi)的變量,里層的for循環(huán)會(huì)覆蓋變量i,所以現(xiàn)在的結(jié)果是3而不是10。所以使用var聲明時(shí),它不在乎你聲明多少次你只會(huì)得到1個(gè)。
setTimeout中的異常
看下面這段代碼:
for (var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 100 * i); }
我們期望的結(jié)果是:每隔100*i毫秒打印出1個(gè)數(shù)字,順序?yàn)?-10,但實(shí)際打印出的全部都是10。這是因?yàn)閟etTimeout在若干毫秒后執(zhí)行一個(gè)函數(shù),并且是在for循環(huán)結(jié)束后。 for循環(huán)結(jié)束后,i的值為10。 所以當(dāng)函數(shù)被調(diào)用的時(shí)候,它會(huì)打印出 10!我們不得不利用一個(gè)立即執(zhí)行函數(shù)解決這個(gè)問(wèn)題:
for(var i = 0; i < 10; i++){ (function(i){setTimeout(()=>console.log(i), i * 100);})(i) }
var聲明的變量帶給我們這么多困擾,所以在typescript中加入了let對(duì)變量進(jìn)行聲明。
let聲明let與var的寫(xiě)法一致:
let hello = "Hello!";
let聲明的變量和var聲明的變量有很多不同之處,let解決了var變量帶來(lái)的困擾。
塊作用域
當(dāng)用let聲明一個(gè)變量,它使用的是塊作用域。 不同于使用 var聲明的變量那樣可以在包含它們的函數(shù)外訪(fǎng)問(wèn),塊作用域變量在包含它們的塊或for循環(huán)之外是不能訪(fǎng)問(wèn)的。
function f(input: boolean) { let a = 100; if (input) { let b = a + 1; return b; } return b; }
在上面代碼中,a可以在if語(yǔ)句中被訪(fǎng)問(wèn),因?yàn)閍在函數(shù)語(yǔ)句中聲明,在if語(yǔ)句之外,而b就不能在if語(yǔ)句塊之外被訪(fǎng)問(wèn),因?yàn)閎是在if語(yǔ)句塊中被聲明的。
在catch語(yǔ)句里聲明的變量也具有同樣的作用域規(guī)則。
try { throw "oh no!"; } catch (e) { console.log("Oh well."); } console.log(e); //error
在catch語(yǔ)句塊外,e是不能被訪(fǎng)問(wèn)的。
在let語(yǔ)句聲明之前訪(fǎng)問(wèn)let聲明的變量,結(jié)果為undefined。
function foo() { // okay to capture "a" return a; } console.log(foo()); // let a = 10;
重定義及屏蔽
var聲明時(shí),不論你聲明多少次,你只會(huì)得到1個(gè)。
var x = 10; console.log(x); //10 var x = 20; console.log(x); //20
let聲明,需要遵循塊作用域規(guī)則,在一個(gè)塊作用域中重復(fù)聲明變量會(huì)產(chǎn)生錯(cuò)誤提示,另一個(gè)用var聲明也不允許。
function g() { let x = 100; var x = 100; // error: can"t have both declarations of "x" }
塊級(jí)作用域變量可以用函數(shù)作用域變量來(lái)聲明。 但是塊級(jí)作用域變量需要在明顯不同的塊里聲明。
function f(condition, x){ if(condition){ let x = 100; return x; } return x; } console.log(f(true, 0)); //100 console.log(f(false, 0)); //0
在一個(gè)嵌套作用域里引入一個(gè)新名字的行為稱(chēng)做屏蔽。 它是一把雙刃劍,它可能會(huì)不小心地引入新問(wèn)題,同時(shí)也可能會(huì)解決一些錯(cuò)誤。 例如,假設(shè)我們現(xiàn)在用 let重寫(xiě)之前的sumMatrix函數(shù)。
function sumMatrix(matrix: number[][]){ let sum = 0; for(let i = 0; i < matrix.length; i++){ let current = matrix[i]; for(let i = 0; i < current.length; i++){ sum += current[i]; } } return sum; } console.log(sumMatrix([[1,2],[3,4]])); //10
這次可以得到正確的結(jié)果10,因?yàn)閮?nèi)層循環(huán)中的i屏蔽了外層循環(huán)中的i。但這種寫(xiě)法是不推薦的。
塊級(jí)作用域變量的獲取
function theCityThatAlwaysSleeps() { let getCity; if (true) { let city = "Seattle"; getCity = function() { return city; } } return getCity(); }
上面這段代碼可以正常執(zhí)行。因?yàn)槲覀円呀?jīng)在city的環(huán)境里獲取到了city,所以就算if語(yǔ)句執(zhí)行結(jié)束后我們?nèi)匀豢梢栽L(fǎng)問(wèn)它。
當(dāng)let聲明出現(xiàn)在循環(huán)體里時(shí)擁有完全不同的行為,針對(duì)每次迭代都會(huì)創(chuàng)建一個(gè)新作用域。所以在 setTimeout例子里我們僅使用let聲明就可以了。
for(let i = 0; i < 10; i ++){ setTimeout(()=>console.log(i), i*100); }
會(huì)輸出與預(yù)料一致的結(jié)果:1 2 3 4 5 6 7 8 9
const 聲明const 聲明是聲明變量的另一種方式。它們與let聲明相似,但是就像它的名字所表達(dá)的,它們被賦值后不能再改變。
const numLivesForCat = 9;
它們擁有與 let相同的作用域規(guī)則,但是不能對(duì)它們重新賦值。
const kitty = { name: "Aurora", numLives: numLivesForCat, } // Error kitty = { name: "Danielle", numLives: numLivesForCat };
但const變量?jī)?nèi)部的狀態(tài)還是可以改變的。
const kitty = { name: "Aurora", numLives: numLivesForCat, } // all "okay" kitty.name = "Rory"; kitty.name = "Kitty"; kitty.name = "Cat"; kitty.numLives--;let與const的區(qū)別
最后,說(shuō)說(shuō)let與const的區(qū)別,引用官網(wǎng)的建議:
使用最小特權(quán)原則,所有變量除了你計(jì)劃去修改的都應(yīng)該使用const。 基本原則就是如果一個(gè)變量不需要對(duì)它寫(xiě)入,那么其它使用這些代碼的人也不能夠?qū)懭胨鼈?,并且要思考為什么?huì)需要對(duì)這些變量重新賦值。 使用 const也可以讓我們更容易的推測(cè)數(shù)據(jù)的流動(dòng)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://hztianpu.com/yun/93494.html
摘要:聯(lián)合類(lèi)型,指賦值的時(shí)候可以是聯(lián)合類(lèi)型中的某一個(gè)。任意屬性允許創(chuàng)建對(duì)象的時(shí)候,定義接口中沒(méi)有的屬性。常見(jiàn)的類(lèi)型推論,還提現(xiàn)在函數(shù)表達(dá)式中。 typeScript是什么? TypeScript 是 JavaScript 的一個(gè)超集,主要提供了類(lèi)型系統(tǒng)和對(duì) ES6 的支持 安裝typeScript npm install -g typeScript 安裝完成查看版本: tsc -v typ...
摘要:聲明和結(jié)構(gòu)在中,支持和這樣的聲明方式。解構(gòu)就是將聲明的一組變量與相同結(jié)構(gòu)的數(shù)組或者對(duì)象的元素?cái)?shù)值一一對(duì)應(yīng),并將變量相對(duì)應(yīng)元素進(jìn)行賦值。 學(xué)習(xí)Angular 2 , 《揭秘Angular 2》讀書(shū)筆記。Angular2 選擇 TypeScript 作為其官方最主要的構(gòu)建語(yǔ)音,這意味著掌握 TypeScript 語(yǔ)音將更有利于高效地開(kāi)發(fā) Angular 應(yīng)用。 聲明和結(jié)構(gòu) 在TypeScr...
摘要:弄了一個(gè)持續(xù)更新的筆記,可以去看看,鏈接地址此篇文章的地址使用兩年后值得嗎基礎(chǔ)筆記的地址可以也可以。使用,你可以使用抽象類(lèi)等功能。有關(guān)抽象類(lèi)的更多信息支持,和方法,只讀屬性。 弄了一個(gè)持續(xù)更新的github筆記,可以去看看,鏈接地址:Front-End-Basics 此篇文章的地址:使用TypeScript兩年后-值得嗎? 基礎(chǔ)筆記的github地址:https://githu...
摘要:注意變量聲明沒(méi)有指定類(lèi)型。因此,程序使用類(lèi)型推斷來(lái)確定變量的數(shù)據(jù)類(lèi)型,第一次賦值為,設(shè)置為類(lèi)型。 typescript 的基本類(lèi)型1.number 數(shù)字類(lèi)型 example: let val: Number = 22.string 字符串 example: let val: String = 23.Boolean 布爾類(lèi)型 example: let val: Boolean = fal...
閱讀 895·2021-11-23 09:51
閱讀 2677·2021-10-11 11:10
閱讀 1490·2021-09-23 11:21
閱讀 1280·2021-09-10 10:50
閱讀 1031·2019-08-30 15:54
閱讀 3470·2019-08-30 15:53
閱讀 3426·2019-08-30 15:53
閱讀 3342·2019-08-29 17:23