1 JavaScript 簡稱JS,是一種動態的弱類型腳本解釋型語言,和HTML,CSS併成爲三大WEB核心技術,獲得了幾乎全部主流瀏覽器的支持 node
1994年,網景Netscape公司成立併發布了Netscape navigator瀏覽器,佔據了很大的時長份額,網景意識到WEB須要動態,須要一種技術來實現
1995年9月網景瀏覽器2發佈測試版本發佈了livescript,隨即在12月的測試版就改名爲JavaScript,同時期,微軟推出IE並支持JScript,VBScript。
1997年,網景,微軟,SUN,borland公司和其餘組織在ECMA肯定了ECMAscript語言標準,JS則是ECMAscript的標準實現之一。python
因爲IE的捆綁銷售行爲,網景的單一瀏覽器時長萎縮,從1990年的90%降低到2006年的1%,1999年網景被AOL收購,收購不就,netspace公開了瀏覽器代碼,並建立了Mozilla組織,Mozilla組織使用Gelo引擎重寫瀏覽器,固然Mozilla將Geko引擎發佈了Firefox瀏覽器
2003年5月,網景被解散
AOL於2007年宣佈中止支持Netscape瀏覽器 正則表達式
HTTP cookie ,解決HTTP無狀態
JavaScript
ssl協議
jar 格式文件,將Java的class文件打包,並加上簽名
2012年4月9日,微軟以10億5千6百萬購買800向美國在線的專利或專利受權,並收購了SSL,cookie等專利。express
ES,ECMAScript是由ECMA國際(前身爲歐洲計算機制造協會,英文名稱是European Computer Manufactures Association)經過ECMA-262標準化的腳本程序設計語言,該語言被普遍應用於互聯網npm
JavaScript是商品名,目前商標權在Oracle公司手中,ES是標準名。數組
根據ES標準,有不少實現引擎,其中包括JavaScript或JScript,他們都是ECMA-262標準的實現和擴展。瀏覽器
1997年,制定了首個ECMA-262服務器
1999年12月,EC3,支持更強大的正則表達式markdown
ES4 太過激進,最終被放棄cookie
2009年,ES5發佈,獲得普遍支持,支持嚴格模式,支持Json
2015年,ES6發佈,引入很是多的新的語言特性,還兼容舊版本的特性,ES6以前按照版本號命名,從ES6開始使用年份做爲版本號,ES6 及ECMAscript 2015.
運行HTML,CSS,JS技術都在發展,標準版本不少,瀏覽器內嵌的引擎實現不太一致,甚至有不按照標準實現,或者減小實現,或者改變實現,或者增長的功能,如IE,就致使了開發人員負擔,很難作到一套代碼能夠兼容的跑在多種瀏覽器中,甚至不能跑在同一種瀏覽器的不一樣版本中。
就在瀏覽器IE一家獨大時,Firefox和Chrome開始變強
2008年9月2日,Google的Chrome瀏覽器發佈,一併發佈的js引擎,就是V8引擎,V8使用BSD協議開源
V8引擎支持C++開發,將JavaScript編譯成了機器碼,而不是字節碼,仍是用不少優化方式提升性能,所以,V8引擎速度很快。
V8 引擎還能夠獨立運行,能夠嵌入到其餘任何C++程序中。
V8 引擎的誕生,使得服務器端運行JS稱爲了方便的事情。
nodejs是服務器端運行JavaScript的開源的,跨平臺的運行環境
nodejs原始做者瑞安達爾於2009年發佈,使用了V8引擎,並採用事件驅動,非阻塞異步IO模型
2010年,npm軟件包管理器誕生,經過它,能夠方便的發佈,分析nodejs的庫和源代碼。
nodejs4.0引入了ES6的語言特性。
須要安裝nodejs和visual studio code
相關下載nodejs
https://npm.taobao.org/mirrors/node/v12.10.0/node-v12.10.0-x64.msi
visual studio code
插件NodeExec和漢化包安裝
從新啓動軟件便可生效,
和C 、Java同樣
//單行註釋
/*註釋*/多行註釋,也可使用在語句中
注: 使用快捷鍵F8運行代碼,其代碼必須是已經保存的文件,不能是空,F8可能和有道詞典快捷鍵衝突,建議在此運行期間不運行有道詞典。
1 標識符
標識符必須是字母,下滑線,美圓符號和數字,但必須是字母,下劃線,美圓符號開頭,依然不能是數字開頭
標識符區分大小寫
2 標識符的聲明
var 聲明一個變量
let 聲明一個塊做用域中的局部變量
const 聲明一個常量JS中的變量聲明和初始化時能夠分開的
常量的存放位置和變量是不在一塊兒的
console.log(a) // 後面聲明的變量,前面可使用,但沒意義 var a //只是聲明,並未賦值,其類型是undefined, let b //聲明爲塊變量 console.log(1,a,b) //打印 a=1 //變量賦值,不規範化操做,不推薦,在嚴格模式下回致使異常。在賦值以前不能引用,由於未爲進行聲明,其賦值的結果是全局做用域 b='123' console.log(2,a,b) const c=100 //定義常量 console.log(c) var d=10 //規範聲明並初始化 console.log(3,d) c=200 //修改常量值,不可修改,由於其是常量 console.log(4,c)
結果以下
常量和變量的選擇
若是明確知道一個標識符定之後便再也不改變,應該儘可能聲明成const常量,減小被修改的風險,減小bug。
function test(){ var x=10; //聲明並初始化x y=20; //聲明vi可以初始化y console.log(x,y) } test() console.log(x,y) //此處在函數中,其全部參數皆不能衝破做用域 // x=100 // console.log(x)
結果以下
函數自己天生就是一個做用域
其實就是將聲明定義到最前面罷了,及就是先調用,再定義
console.log(a) console.log(b) console.log(c) console.log(d) console.log(e) var a=200; // 提高做用域,只有var定義變量的方式能夠提高做用域 var b; const c=300; //此處不能提高做用域 let d; e=300;
結果以下
序號 | 名稱 | 說明 |
---|---|---|
1 | number | 數值型,包括整數類型和浮點型 |
2 | boolean | 布爾型,true和false |
3 | string | 字符串 |
4 | null | 只有一個值null |
5 | undefined | 變量聲明未賦值的,對象未定義的屬性 |
6 | symbol | ES6新引入的類型 |
7 | object類型 | 是以上基本類型的複合類型,是容器 |
ES是動態語言,弱類型語言
雖然先聲明瞭變量,可是變量能夠從新賦值成任何類型
console.log(a=1+'test',typeof(a)) // typeof:打印類型 console.log(a=false+'test',typeof(a)) //和布爾類型運算 console.log(a=null+'test',typeof(a)) //和null比較 console.log(a=true+'test',typeof(a)) console.log(a=undefined+'test',typeof(a)) //和數字
結果以下
console.log(a=1+false,typeof(a)) console.log(a=1+true,typeof(a)) console.log(a=1+null,typeof(a)) console.log(a=1+undefined,typeof(a))
結果以下
console.log(a=false+undefined,typeof(a)) console.log(a=true+undefined,typeof(a)) console.log(a=false+null,typeof(a)) console.log(a=true+null,typeof(a)) console.log(a=true & '',typeof(a)) //位運算 console.log(a=undefined && true,typeof(a)) //與運算
True是透明的,false則直接就是短路,返回直接就是false,類型是布爾。true主要是看後面的狀況
console.log(a=false && null,typeof(a)) //若是前面是false,則返回結果是false,且類型是布爾類型 console.log(a=false && 'zhangbing',typeof(a)) console.log(a=true && '32534534',typeof(a)) //若是前面是true,則之後面爲準 console.log(a=true && '' ,typeof(a))
弱類型,不須要強制轉換
NaN,Not a Number,轉換數字失敗
遇到字符串,加括號就是拼接字符串,全部非字符串隱式轉換爲字符串
若是沒有字符串,加號把其餘全部類型都當數字處理,非數字類型隱式轉換成數字,undefined特殊,由於它都沒有定義值,全部其是一個特殊的數字Nan。
若是運算符是邏輯運算符,短路符,則返回就是短路時的類型,沒有隱式轉換
除非你十分明確,不然不要依賴隱式類型轉換,寫代碼時,每每爲了程序的健壯性,建議顯式轉換
將一個值一單引號或雙引號引用後便造成了字符串
let a="a\"aaaaaa" // 可以使用轉義符號 let b='adadsaasd' //單引號定義 let c="asfsdfsadfsdf'sdfsdfsdfsdf'" //混合定義 let d=`'abcd'` //反引號定義 let e=`x= ${a} y=${b}` //插值,相似於Java中的替換和python中的format console.log(a,b,c,d) console.log(e)
結果以下
字符 | 說明 |
---|---|
\0 | Null 字節 |
\b | 退格符 |
\f | 換頁符 |
\n | 換行符 |
\r | 回車符 |
\t | Tab(製表符) |
\v | 垂直製表符 |
' | 單引號 |
" | 雙引號 |
|反斜槓字符() | |
\XXX | 由從0到377最多三個八進制數XXX表示的Latin-1字符 |
\xXX | 由從00和FF的兩位十六進制數字XX表示的Latin-1字符 |
\uXXXX | 由4位十六進制數字XXXX表示的Unicode字符,例如,\u00A9是版權符號的Unicode序列,見Unicode escape sequence |
\u{xxxxxx} | Unicode代碼點(code point)轉義字符 |
支持索引,切片,查詢,替換和連接
console.log('adasddasdasd'.indexOf(1)) //查找位置,若不存在,則返回-1 console.log('abced'.indexOf('c')) //獲取對應位置 console.log('12345'.charAt(4)) //索引獲取元素 console.log('1234'.concat('666')) // 元素追加 const a='123456' //定義一個常量 console.log(a[3]) //經過索引獲取元素 console.log(a.toUpperCase()) //大寫轉換 console.log(a.slice(1,3)) //切片,左閉右開 1,2處的元素 console.log(a.slice(-3,-1)) //45 const url=' www.baidu.com ' console.log(url.split('.')) //字符串分割 console.log(url.startsWith('www')) //匹配字符串起始,返回false或true console.log(url.substr(3,6)) //從索引爲3開始6個字符 console.log(url.substr(3,6)) //從索引爲3開始到索引爲6結束 console.log(url.replace('com','edu')) //字符串一替換 console.log(url.trim()) //取出兩邊的空白字符
進制符 | 描述 |
---|---|
0bxxx/0Bxxx | 二進制 |
0oxxx | 八進制 |
0xxxx | 十六進制 |
在JS中,數據均爲雙精度浮點型範圍只能在-(2^53-1)和2^53-1之間,整數類型也不例外,數字類型還有三種符號值:+Infinity(正無窮),-Infinity(負無窮)和Nan(not-a-number非數字)
二進制0b0010,0B100.
八進制0755,注意0855,將被認做是十進制,由於8不在八進制中,ES6中最好使用0o 前綴表示八進制
十六進制0xAA,0xff
指數表示1E3(1000),2e-2(0.02)
常量屬性
var biggestNum=Number.MAX_VALUE; //最大值 var smallestNum=Number.MIN_VALUE; //最小的大於0的數 var infiniteNum=Number.POSITIVE_INFINITY; var negInfiniteNum=Number.NEGATIVE_INFINITY; var notANum=Number.NaN;
數字方法
方法 | 描述 |
---|---|
Number.paraseFloat() | 把字符串參數解析成浮點數,和全局方法parseFloat()做用同樣 |
Number.parseLnt() | 把字符串解析成特定基數對應的整數類型數字,和全局方法parseInt()做用一致 |
Number.isFinite() | 判斷傳遞的值是否爲有限數字 |
Number.isInteger() | 判斷傳遞的值是否爲整數 |
Number.isNaN() | 判斷傳遞的值是不是NaN |
內置數學對象Math
Math提供了絕對值,對數指數運算,三角函數運算,最大值,最小值,隨機數,開方等運算函數,提供了P|值
console.log(typeof(parseInt('1234123423423')),'134234') //轉換爲數值類型 console.log(isNaN(10)) //判斷是否爲NaN console.log(isFinite(10/3)) console.log(Math.abs(-1)) //絕對值 console.log(Math.random()*1000) //生成隨機數
符號 | 描述 |
---|---|
+ | 加 |
- | 減 |
* | 乘 |
/ | 除 |
% | 餘 |
++i | 單目運算符先加後賦值 |
i++ | 單目運算符先賦值後加 |
--i | 單目運算符先減後賦值 |
i-- | 單目運算符先賦值後減 |
單目運算符,自增和自減只針對一個參數的運算符
++ 和 --
i++ 表示先用,後加,其加的值爲1
++i 表示先加,後用,其加的值也是1
總之,誰在左,誰先執行
反之--也是亦然。
let i=0; a=i++ //此處是先用後加,所以其a的值應該是0,以後加1 console.log(a) b=++i; //此處是先加後用,此處的b的值應該是i爲1的基礎是加1,及爲2 console.log(b) c=i++; //此處是先用,及c爲2 console.log(c)
結果以下
其中單目運算符的優先級高於雙目運算符。
相關習題
let i=0; a=(++i+i+++i+++i) //其中單目優先級高,則可拆解爲 ++i + i++ + i++ +i //++i結果爲1 ,i++結果i爲1 i++ 結果i爲2 i的結果爲3 最終爲1+1+2+3=7 console.log(a)
結果以下
此題主要考慮兩個點
1 單目運算符優先級高於雙目運算符
2 加號+是雙目運算符,兩邊的表達式必須先計算好
符號 | 描述 |
---|---|
> | 大於 |
< | 小於 |
>= | 大於等於 |
<= | 小於等於 |
!= | 不等於,寬鬆模式進行類型轉換 |
== | 寬鬆模式等於,及就是進行類型轉換 |
!== | 嚴格模式不等於,及不進行類型轉換 |
=== | 恆等,及全等,不進行類型轉換 |
console.log('1'==1) //此處爲寬鬆模式,進行類型轉換,此處爲true console.log('1'===1) //此處爲嚴格模式,此處返回爲False console.log('200'>300) //此處爲true,進行了類型轉換 console.log('2a'<200) //此處爲false,此處的2a是不能轉換爲數字的,所以不能參與比較,所以其返回值爲false console.log(Number.MAX_VALUE>10000) //和最大比較,返回爲true console.log(Number.MIN_VALUE < 0.00001) //和最小比較,範圍爲true console.log(Number.MAX_VALUE>Number.MIN_VALUE) //最大和最小比較,返回爲true
結果以下
Column 1 | Column 2 |
---|---|
&& | 邏輯與 |
|| | 邏輯或 |
! | 邏輯非 |
這些運算符和其餘高級語言相同。支持短路。
方法 | 描述 |
---|---|
& | 位與 |
| | 位或 |
^ | 異或 |
~ | 取反 |
<< | 左移 |
>> | 右移 |
條件表達式?真值:假值,鄧建與簡單的if ...else 結構
console.log(('3'>30)?'真':'假') console.log((4<5)?'假':'真')
JS 運行多個表達式寫在一塊兒的狀況
console.log(a,b,c) var a=100,b=200,c=300 //提高做用域,會定義三個元素
結果以下
詳情見 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
名稱 | 說明 |
---|---|
Instanceof | 判斷是否屬於指定類型 |
typeof | 返回類型字符串 |
delete | delete操做符,刪除一個對象(an object)或者一個對象的屬性(an object's property) 或者一個數組中的某一個鍵值(an element at a specified index in an array)。 |
in | 若是指定的屬性在對象內,則返回true |
instanceof 要求必須明確使用類型定義變量,就是對象必須是new關鍵字聲明建立的,它能夠用於繼承關係的判斷
typeof 就是返回對象的類型字符串
delete刪除對象,屬性,數組元素
a=new String('abcd') b=new Number(123) console.log(a instanceof String) console.log(b instanceof Number) console.log(typeof(a)) console.log(typeof(b)) console.log(typeof(100)) console.log('--------------delete-----------') x=42 var y=43 let z=60 myobj=new Number(); myobj.h=4 //增長屬性 console.log(delete x); //隱式聲明使用delete可以刪除成功 console.log(delete y); //var聲明的不能刪除 console.log(delete z); //let聲明的依然不能刪除 console.log(delete myobj.PI) //不能刪除預約義的對象, console.log(delete myobj.h) // 自定義的屬性變量是能夠刪除的 console.log(delete myobj) //自定義的對象能夠刪除,由於其是隱式聲明,所以能夠刪除 console.log('+++++++++++++++++++') var trees = new Array('redwoord','bay','cendar','cak','maple') for (var i=0;i<trees.length;i++) console.log(trees[i]) console.log('====================') delete trees[3];//刪除其中的元素,其數組不會少,只會在當前索引對應的數據變爲undefined for (var i=0;i<trees.length;i++) console.log(trees[i]) console.log('-------------object----------------') let mycar ={ make:'Honda', model:'Accord',year: 2019 }; console.log('make' in mycar); //true console.log('model' in mycar); //true
結果以下
if (cond1) { } else if (cond2) { } else if (cond3) { } else { }
條件爲false的等效
false
undefined
null
0
NaN
空字符串其餘的將均被視爲True,如空列表。
if ([]) { let d=4;//定義爲塊變量,其不能穿透if var e=5; //var 定義,可以穿透if f=6; //定義,可以穿透 if (true) { console.log(d); console.log(e); console.log(f); g=10; var h=11; let t=13;//定義爲塊變量,其不能穿透if } } console.log(h,g,f) console.log(t)
結果以下
switch (expression) { case label_1: statements_1 [break;] case label_2: statements_2 [break;] ... default: statements_def [break;] }
let a=3 switch (a) { case 1: console.log(1) break; case 2: console.log(2) break; case 3: console.log(3) break; default: console.log(4) break; }
結果以下
switch的穿透效果,直到遇見break爲止。
let a=3 switch (a) { case 1: console.log(1) case 2: console.log(2) case 3: console.log(3) default: console.log(4) }
結果以下
//C風格for循環
for ([initialExpression];[condition];[incrementExpression]) { statement }
arr=[10,20,30] for (let x=0;x<arr.length;x++){ console.log('i',arr[x]) } console.log('+++++++++++++++++') for (let j=0;j<arr.length;j++,j++) { //注意,此處是逗號(i++,i++) console.log('j',arr[j]) } // for (z=0;z<arr.length;) { // 此處是死循環,由於沒有增長條件 // console.log(arr[z]) // } for (let a=0,b=200;a<arr.length;a++,b++) { // 多條件操做 console.log(a,arr[a],b); } for ( let z in arr) { //此處獲取到的是索引 console.log(z,arr[z]) } for (let w of arr) { //此處獲取到的是值 console.log(w) } let obj={'a':1,'b':2,'c':3} for (let x in obj) { //使用for循環處理對key的訪問 console.log('obj',x) } // for (let y of obj) { //此處不能實現,由於其不能迭代對象 // console.log(y) // }
結果以下
注意:for in 循環返回的是索引或者key,須要間接訪問到值。
數組反正返回的是索引,C風格for循環操做較爲便利
對象使用for in 能夠遍歷其key,但不能使用for of 迭代對象,緣由是of後面必須是一個迭代器,可類比python中的for in。
while 循環通常適用於死循環,while循環是先判斷,do...while循環是先執行,後判斷。
while (condition){ statement }
do { statement } while(condition)
先進入循環,而後判斷,爲真就繼續循環
let x=10; while (x--){ console.log(x) }
結果以下
let x=10; do { console.log(x) }while(x--)
結果以下
break 結束當前循環,直接退出這個循環體
continue 中斷當前循環,直接進入下一次循環,同一個循環中的某一個跳過練習
打印9*9乘法口訣
for (i=1;i<10;i++) { line=" " for (j=1;j<=i;j++){ line += `${j}*${i} = ${i*j} ` if (i==j) console.log(line); } }
函數: 函數也是對象
格式以下
function 函數名(參數列表) { 函數體; return 返回值; }
示例以下
function add(x,y){ return x+y; } console.log(add(4,5))
結果以下
使用表達式來定義函數,表達式中的函數名能夠省略,若是這個函數名不省略,也只能用於該函數的內部。
const add =function _add(x,y) { return x+y; } console.log(_add(4,5))
結果以下
const add =function _add(x) { if (x==1){ return x; } return _add(x-1)+x //遞歸調用,該函數只能在其內部被調用 } console.log(add(10))
結果以下
const add =function (x,y) { //匿名函數 return x+y; } console.log(add(4,5))
console.log(show) function show(){ //函數能夠提高做用域 console.log('show') } console.log(add) var add=function(){ //函數表達式則不能提高做用域 return 1; }
結果以下
函數,匿名函數,函數表達式的差別
函數和匿名函數,本質上都是同樣的,都是函數對象,只不過函數有本身的標識符--函數名。匿名函數須要藉助其餘標識符而已。
區別在於,函數會聲明提高,函數表達式不會。
高階函數:參數爲函數或返回值爲函數的函數稱爲高階函數
function a(){ console.log('a') return function b(){ console.log('b') return 'b' //函數必須有返回值,不然,返回爲undefined } } console.log(a()) //調用外層函數 console.log(a()()) //因爲a返回值函數,所以可使用括號來進行相關的調用操做
結果以下
let counter=function() { let i=0; function _fun(){ return ++i; } return _fun } c=counter() console.log(c()) console.log(c()) console.log(c()) console.log(c())
結果以下
實現map函數的功能,傳入一個函數,傳入一個值,輸出一個值處理後的狀況,如輸入1,2,3,4,輸出爲1 4 9 16 及平方
const map1= function (fn,arr){ newarry=[]; for (i in arr){ newarry[i]=fn(arr[i]); } return newarry; } const sq = function(x){ return x*x; } console.log(map1(sq,[1,2,3,4]))
箭頭函數就是匿名函數,它是一種更加精簡的格式
箭頭函數參數
若是一個函數沒有參數,則使用()
若是隻有一個參數,參數列表能夠省略小括號
多個參數不能省略小括號,且使用逗號間隔
箭頭函數返回值
若是函數體部分有多行,就須要使用{},若是有返回值則使用return。
若是隻有一行語句,能夠同時省略大括號和return
只有一條return語句,不能省略大括號,有return必須有大括號
若是隻有一條非return語句,加上大括號,函數無返回值
將上述實例中的函數修改成箭頭函數
const map1= (fn,arr) => { newarry=[]; for (i in arr){ newarry[i]=fn(arr[i]); } return newarry; } const sq = (x) => x*x; console.log(map1(sq,[1,2,3,4]))
結果以下
const map1= (fn,arr) => { newarry=[]; for (i in arr){ newarry[i]=fn(arr[i]); } return newarry; } let new1 = map1((function (x) {return x*x}),[1,2,3,4]) //函數 let new2=map1((x)=> {return x*x},[1,2,3,4] ) //去除function ,將後面的變爲(x) => {return x}形式 let new3 =map1((x)=> x*x,[1,2,3,4]) //若只有一個返回值,則能夠省略{},但{} 和return是同時存在,所以能夠寫成以下 let new4 =map1( x => x*x,[1,2,3,4]) //若是隻有一個參數,則能夠省略() console.log(new1) console.log(new2) console.log(new3) console.log(new4)
結果以下
const add = (x,y) => x+y; console.log('add',add(4,5)) const add1 = (x,y=5) => x+y; //支持默認參數 console.log('add1',add1(4)) const add2 = (x=6,y) => x+y; console.log('add2',add2(1)) //此處默認會將x=6代替爲x=1,而y的值爲undefined其傳入的值爲add2(1,undefined) console.log('add2',add2(1,10)) console.log('add2',add2(y=10,z=20)) //此處的結果爲30,其不關心形式參數,此處爲add2(10,20) console.log('add2',add2(a=1000,b=3000,c=4000)) //多傳遞參數沒錯,只匹配前面的
結果以下
JS 基本參數總結
1 JS 中並無python中的關鍵字傳參
2 JS 只是再作參數位置的對應
3 JS 並不限制默認參數的位置
4 JS 多傳遞參數沒影響,其只是作位置的匹配操做
const add = (...args) => { // 可變參數 ,默認結果爲列表 result=0; console.log(args); for (let x in args) { result += args[x]; } return result; } console.log(add(1,2,3,4,5))
和python 相似,JS提供了參數解構,依然使用了...符號來解構。
const add =(...args) => { console.log(args) } add(1,2,3,4) l1=[1,2,3,4] add(l1) //參數解構 console.log(...l1) add(...l1)
結果以下
函數的全部參數都會被保存在一個arguments的鍵值對字典對象中。
(function (p1,...args) { console.log(p1); console.log(args); console.log('---------------'); console.log(arguments,typeof(arguments)); for (let x of arguments) console.log(x); })('abcd',1,2,3,4,5) //此處是調用操做
結果以下
全局對象
console.log(arguments)
結果以下
在函數外,其指的是全局的,在函數內,其是函數中的參數
基本表達式和python差很少
function * inc(){ //使用* 來定義生成器 let i=0; while (1) yield (++i); } g=inc() //實例化生成器 console.log(g.next().value,g.next()) //執行生成器調用 console.log(g.next().value) console.log(g.next().value) console.log(g.next().value,g.next())
結果以下
每次調用next()方法返回一個對象,這個對象包含兩個屬性: value和done,value屬性表示本次yield表達式的返回值,done屬性爲布爾值,done是false表示後續還有yield語句執行,若是執行完成或者return後,none爲true。
function * inc(){ let i=0; while (true) { yield ++i; if (i>3) return i; } } g= inc() console.log(g.next()) console.log(g.next()) console.log(g.next()) console.log(g.next()) console.log(g.next())
結果以下
JS 使用大括號構成語句塊
ES6 以前語句塊是沒有做用域的,從ES6開始支持塊做用域,let只能在塊做用域中可見。
function hello(){ let a=1; var b=2; c=3 } let d=100 if (1) { let d=4; //局部和下一級有效,除非被覆蓋掉 var e=5 f=6 if (true) { console.log(d) console.log(e) console.log(f) console.log('____________________') g=10 //只要不是函數,都沒問題 var h=11 //只要是函數,都沒問題 } } //console.log(a) //不可見 //console.log(b) //不可見 //console.log(c) //不可見 console.log(d) //不可見 let 突破不了塊做用域,但外界共享 console.log(e) //var可見 console.log(f) //隱式聲明,可見 console.log(g) //可見 console.log(h) //可見
結果以下
塊做用域只對let有效,對var和隱式聲明等特性無效 函數中var 和 let 都突破不了 塊做用域向下是穿透的,除非覆蓋問題