摘要:本部分主要是針對(duì)于中常用的數(shù)據(jù)結(jié)構(gòu)類型進(jìn)行分析說(shuō)明。原始類型數(shù)值字符串布爾值分別返回。函數(shù)將字符串轉(zhuǎn)為數(shù)值,要比函數(shù)嚴(yán)格很多。表示沒(méi)有對(duì)象,即該處不應(yīng)該有值。作為對(duì)象原型鏈的終點(diǎn)。調(diào)用函數(shù)時(shí),應(yīng)該提供的參數(shù)沒(méi)有提供,該參數(shù)等于。
[TOC]
本部分主要是針對(duì)于JavaScript中常用的數(shù)據(jù)結(jié)構(gòu)類型進(jìn)行分析說(shuō)明。
變量與常量在JavaScript中,基本的變量聲明可以用var方式。JavaScript允許省略var,直接對(duì)未聲明的變量賦值。也就是說(shuō),var a = 1 與 a = 1,這兩條語(yǔ)句的效果相同。但是由于這樣的做法很容易不知不覺(jué)地創(chuàng)建全局變量(尤其是在函數(shù)內(nèi)部),所以建議總是使用var命令聲明變量。
在ES6中,對(duì)于變量聲明的方式進(jìn)行了擴(kuò)展。引入了let方式,let即是定義塊級(jí)別的變量,不會(huì)以閉包方式擴(kuò)展到塊外面。另一種引入了可以用于定義常量的const聲明。
function f() { { let x; { // okay, block scoped name const x = "sneaky"; // error, const x = "foo"; } // error, already declared in block let x = "inner"; } }變量作用域 變量提升
JavaScript是解釋執(zhí)行的語(yǔ)言, JavaScript引擎的工作方式是,先解析代碼,獲取所有被聲明的變量,然后再一行一行地運(yùn)行。這造成的結(jié)果,就是所有的變量的聲明語(yǔ)句,都會(huì)被提升到代碼的頭部,這就叫做變量提升(hoisting)。
console.log(a); var a = 1;
上面代碼首先使用console.log方法,在控制臺(tái)(console)顯示變量a的值。這時(shí)變量a還沒(méi)有聲明和賦值,所以這是一種錯(cuò)誤的做法,但是實(shí)際上不會(huì)報(bào)錯(cuò)。因?yàn)榇嬖谧兞刻嵘?,真正運(yùn)行的是下面的代碼:
var a; console.log(a); a = 1;
最后的結(jié)果是顯示undefined,表示變量a已聲明,但還未賦值。請(qǐng)注意,變量提升只對(duì)var命令聲明的變量有效,如果一個(gè)變量不是用var命令聲明的,就不會(huì)發(fā)生變量提升。
console.log(b); b = 1;
上面的語(yǔ)句將會(huì)報(bào)錯(cuò),提示“ReferenceError: b is not defined”,即變量b未聲明,這是因?yàn)閎不是用var命令聲明的,JavaScript引擎不會(huì)將其提升,而只是視為對(duì)頂層對(duì)象的b屬性的賦值。
避免全局變量在計(jì)算機(jī)編程中,全局變量指的是在所有作用域中都能訪問(wèn)的變量。全局變量是一種不好的實(shí)踐,因?yàn)樗鼤?huì)導(dǎo)致一些問(wèn)題,比如一個(gè)已經(jīng)存在的方法和全局變量的覆蓋,當(dāng)我們不知道變量在哪里被定義的時(shí)候,代碼就變得很難理解和維護(hù)了。在ES6中可以利用let關(guān)鍵字來(lái)聲明本地變量,好的 JavaScript 代碼就是沒(méi)有定義全局變量的。有一些技術(shù)可以幫助你讓所有的事情都保持在本地:
函數(shù)包裹為了避免全局變量,第一件事情就是要確保所有的代碼都被包在函數(shù)中。最簡(jiǎn)單的辦法就是把所有的代碼都直接放到一個(gè)函數(shù)中去:
(function(win) { "use strict"; // 進(jìn)一步避免創(chuàng)建全局變量 var doc = window.document; // 在這里聲明你的變量 // 一些其他的代碼 }(window));聲明命名空間
var MyApp = { namespace: function(ns) { var parts = ns.split("."), object = this, i, len; for(i = 0, len = parts.lenght; i < len; i ++) { if(!object[parts[i]]) { object[parts[i]] = {}; } object = object[parts[i]]; } return object; } }; // 定義命名空間 MyApp.namespace("Helpers.Parsing"); // 你現(xiàn)在可以使用該命名空間了 MyApp.Helpers.Parsing.DateParser = function() { //做一些事情 };模塊化
另一項(xiàng)開(kāi)發(fā)者用來(lái)避免全局變量的技術(shù)就是封裝到模塊 Module 中。一個(gè)模塊就是不需要?jiǎng)?chuàng)建新的全局變量或者命名空間的通用的功能。不要將所有的代碼都放一個(gè)負(fù)責(zé)執(zhí)行任務(wù)或者發(fā)布接口的函數(shù)中。最常見(jiàn)的 JavaScript 模塊類型就是異步模塊定義 Asynchronous Module Definition (AMD)。
//定義 define( "parsing", //模塊名字 [ "dependency1", "dependency2" ], // 模塊依賴 function( dependency1, dependency2) { //工廠方法 // Instead of creating a namespace AMD modules // are expected to return their public interface var Parsing = {}; Parsing.DateParser = function() { //do something }; return Parsing; } ); // 通過(guò) Require.js 加載模塊 require(["parsing"], function(Parsing) { Parsing.DateParser(); // 使用模塊 });解構(gòu)賦值
解構(gòu)賦值允許你使用類似數(shù)組或?qū)ο笞置媪康恼Z(yǔ)法將數(shù)組和對(duì)象的屬性賦給各種變量。這種賦值語(yǔ)法極度簡(jiǎn)潔,同時(shí)還比傳統(tǒng)的屬性訪問(wèn)方法更為清晰。
傳統(tǒng)的訪問(wèn)數(shù)組前三個(gè)元素的方式為:
var first = someArray[0]; var second = someArray[1]; var third = someArray[2];
而通過(guò)解構(gòu)賦值的特性,可以變?yōu)椋?/p>
var [first, second, third] = someArray;數(shù)組與迭代器
以上是數(shù)組解構(gòu)賦值的一個(gè)簡(jiǎn)單示例,其語(yǔ)法的一般形式為:
[ variable1, variable2, ..., variableN ] = array;
這將為variable1到variableN的變量賦予數(shù)組中相應(yīng)元素項(xiàng)的值。如果你想在賦值的同時(shí)聲明變量,可在賦值語(yǔ)句前加入var、let或const關(guān)鍵字,例如:
var [ variable1, variable2, ..., variableN ] = array; let [ variable1, variable2, ..., variableN ] = array; const [ variable1, variable2, ..., variableN ] = array;
事實(shí)上,用變量來(lái)描述并不恰當(dāng),因?yàn)槟憧梢詫?duì)任意深度的嵌套數(shù)組進(jìn)行解構(gòu):
var [foo, [[bar], baz]] = [1, [[2], 3]]; console.log(foo); // 1 console.log(bar); // 2 console.log(baz); // 3
此外,你可以在對(duì)應(yīng)位留空來(lái)跳過(guò)被解構(gòu)數(shù)組中的某些元素:
var [,,third] = ["foo", "bar", "baz"]; console.log(third); // "baz"
而且你還可以通過(guò)“不定參數(shù)”模式捕獲數(shù)組中的所有尾隨元素:
var [head, ...tail] = [1, 2, 3, 4]; console.log(tail); // [2, 3, 4]
當(dāng)訪問(wèn)空數(shù)組或越界訪問(wèn)數(shù)組時(shí),對(duì)其解構(gòu)與對(duì)其索引的行為一致,最終得到的結(jié)果都是:undefined。
console.log([][0]); // undefined var [missing] = []; console.log(missing); // undefined
請(qǐng)注意,數(shù)組解構(gòu)賦值的模式同樣適用于任意迭代器:
function* fibs() { var a = 0; var b = 1; while (true) { yield a; [a, b] = [b, a + b]; } } var [first, second, third, fourth, fifth, sixth] = fibs(); console.log(sixth); // 5對(duì)象
通過(guò)解構(gòu)對(duì)象,你可以把它的每個(gè)屬性與不同的變量綁定,首先指定被綁定的屬性,然后緊跟一個(gè)要解構(gòu)的變量。
var robotA = { name: "Bender" }; var robotB = { name: "Flexo" }; var { name: nameA } = robotA; var { name: nameB } = robotB; console.log(nameA); // "Bender" console.log(nameB); // "Flexo"
當(dāng)屬性名與變量名一致時(shí),可以通過(guò)一種實(shí)用的句法簡(jiǎn)寫:
var { foo, bar } = { foo: "lorem", bar: "ipsum" }; console.log(foo); // "lorem" console.log(bar); // "ipsum"
與數(shù)組解構(gòu)一樣,你可以隨意嵌套并進(jìn)一步組合對(duì)象解構(gòu):
var complicatedObj = { arrayProp: [ "Zapp", { second: "Brannigan" } ] }; var { arrayProp: [first, { second }] } = complicatedObj; console.log(first); // "Zapp" console.log(second); // "Brannigan"
當(dāng)你解構(gòu)一個(gè)未定義的屬性時(shí),得到的值為undefined:
var { missing } = {}; console.log(missing); // undefined
請(qǐng)注意,當(dāng)你解構(gòu)對(duì)象并賦值給變量時(shí),如果你已經(jīng)聲明或不打算聲明這些變量(亦即賦值語(yǔ)句前沒(méi)有let、const或var關(guān)鍵字),你應(yīng)該注意這樣一個(gè)潛在的語(yǔ)法錯(cuò)誤:
{ blowUp } = { blowUp: 10 }; // Syntax error 語(yǔ)法錯(cuò)誤
為什么會(huì)出錯(cuò)?這是因?yàn)镴avaScript語(yǔ)法通知解析引擎將任何以{開(kāi)始的語(yǔ)句解析為一個(gè)塊語(yǔ)句(例如,{console}是一個(gè)合法塊語(yǔ)句)。解決方案是將整個(gè)表達(dá)式用一對(duì)小括號(hào)包裹:
({ safe } = {}); // No errors 沒(méi)有語(yǔ)法錯(cuò)誤默認(rèn)值
當(dāng)你要解構(gòu)的屬性未定義時(shí)你可以提供一個(gè)默認(rèn)值:
var [missing = true] = []; console.log(missing); // true var { message: msg = "Something went wrong" } = {}; console.log(msg); // "Something went wrong" var { x = 3 } = {}; console.log(x); // 3
由于解構(gòu)中允許對(duì)對(duì)象進(jìn)行解構(gòu),并且還支持默認(rèn)值,那么完全可以將解構(gòu)應(yīng)用在函數(shù)參數(shù)以及參數(shù)的默認(rèn)值中。
function removeBreakpoint({ url, line, column }) { // ... }
當(dāng)我們構(gòu)造一個(gè)提供配置的對(duì)象,并且需要這個(gè)對(duì)象的屬性攜帶默認(rèn)值時(shí),解構(gòu)特性就派上用場(chǎng)了。舉個(gè)例子,jQuery的ajax函數(shù)使用一個(gè)配置對(duì)象作為它的第二參數(shù),我們可以這樣重寫函數(shù)定義:
jQuery.ajax = function (url, { async = true, beforeSend = noop, cache = true, complete = noop, crossDomain = false, global = true, // ... 更多配置 }) { // ... do stuff };
同樣,解構(gòu)也可以應(yīng)用在函數(shù)的多重返回值中,可以類似于其他語(yǔ)言中的元組的特性:
function returnMultipleValues() { return [1, 2]; } var [foo, bar] = returnMultipleValues();Spread Operator(… 擴(kuò)展操作符)
function myFunction(x, y, z) { } var args = [0, 1, 2]; myFunction(...args);
還有另外一個(gè)好處就是可以用來(lái)替換Object.assign來(lái)方便地從舊有的對(duì)象中創(chuàng)建新的對(duì)象,并且能夠修改部分值。譬如
var obj = {a:1,b:2} var obj_new_1 = Object.assign({},obj,{a:3}); var obj_new_2 = { ...obj, a:3 }類型/格式判斷與轉(zhuǎn)換 typeof
typeof運(yùn)算符可以返回一個(gè)值的數(shù)據(jù)類型,可能有以下結(jié)果。
(1)原始類型
數(shù)值、字符串、布爾值分別返回number、string、boolean。
typeof 123 // "number" typeof "123" // "string" typeof false // "boolean"
(2)函數(shù)
函數(shù)返回function。
// 定義一個(gè)空函數(shù) function f(){} typeof f // "function"
(3)undefined
undefined返回undefined。
typeof undefined // "undefined"
利用這一點(diǎn),typeof可以用來(lái)檢查一個(gè)沒(méi)有聲明的變量,而不報(bào)錯(cuò)。
v // ReferenceError: v is not defined typeof v // "undefined"
實(shí)際編程中,這個(gè)特點(diǎn)通常用在判斷語(yǔ)句。
// 錯(cuò)誤的寫法 if (v){ // ... } // ReferenceError: v is not defined // 正確的寫法 if (typeof v === "undefined"){ // ... }
(4)其他
除此以外,都返回object。
typeof window // "object" typeof {} // "object" typeof [] // "object" typeof null // "object"
從上面代碼可以看到,空數(shù)組([])的類型也是object,這表示在JavaScript內(nèi)部,數(shù)組本質(zhì)上只是一種特殊的對(duì)象。另外,null的類型也是object,這是由于歷史原因造成的,為了兼容以前的代碼,后來(lái)就沒(méi)法修改了,并不是說(shuō)null就屬于對(duì)象,本質(zhì)上null是一個(gè)類似于undefined的特殊值。
instanceoftypeof對(duì)數(shù)組(array)和對(duì)象(object)的顯示結(jié)果都是object,那么怎么區(qū)分它們呢?instanceof運(yùn)算符可以做到。
var o = {}; var a = []; o instanceof Array // false a instanceof Array // true類型的自動(dòng)轉(zhuǎn)換
當(dāng)遇到以下幾種情況,JavaScript會(huì)自動(dòng)轉(zhuǎn)換數(shù)據(jù)類型:
不同類型的數(shù)據(jù)進(jìn)行互相運(yùn)算;
對(duì)非布爾值類型的數(shù)據(jù)求布爾值;
對(duì)非數(shù)值類型的數(shù)據(jù)使用一元運(yùn)算符(即“+”和“-”)。
基本類型(Basic) 數(shù)值類型 科學(xué)計(jì)算 隨機(jī)數(shù)random() 方法可返回介于 0 ~ 1 之間的一個(gè)隨機(jī)數(shù)。
類型轉(zhuǎn)換使用Number函數(shù),可以將任意類型的值轉(zhuǎn)化成數(shù)字。
數(shù)值:轉(zhuǎn)換后還是原來(lái)的值。
字符串:如果可以被解析為數(shù)值,則轉(zhuǎn)換為相應(yīng)的數(shù)值,否則得到NaN。空字符串轉(zhuǎn)為0。
布爾值:true轉(zhuǎn)成1,false轉(zhuǎn)成0。
undefined:轉(zhuǎn)成NaN。
null:轉(zhuǎn)成0。
Number函數(shù)將字符串轉(zhuǎn)為數(shù)值,要比parseInt函數(shù)嚴(yán)格很多?;旧?,只要有一個(gè)字符無(wú)法轉(zhuǎn)成數(shù)值,整個(gè)字符串就會(huì)被轉(zhuǎn)為NaN。
parseInt("011") // 9 parseInt("42 cats") // 42 parseInt("0xcafebabe") // 3405691582 Number("011") // 11 Number("42 cats") // NaN Number("0xcafebabe") // 3405691582
如果Number傳入的參數(shù)是一個(gè)對(duì)象,那么轉(zhuǎn)換規(guī)則會(huì)相對(duì)復(fù)雜一點(diǎn),具體而言描述如下:
先調(diào)用對(duì)象自身的valueOf方法,如果該方法返回原始類型的值(數(shù)值、字符串和布爾值),則直接對(duì)該值使用Number方法,不再進(jìn)行后續(xù)步驟。
如果valueOf方法返回復(fù)合類型的值,再調(diào)用對(duì)象自身的toString方法,如果toString方法返回原始類型的值,則對(duì)該值使用Number方法,不再進(jìn)行后續(xù)步驟。
如果toString方法返回的是復(fù)合類型的值,則報(bào)錯(cuò)。
格式化顯示這里用的是numeraljs,格式化顯示的效果如下所示:
Number
Number | Format | String |
---|---|---|
10000 | "0,0.0000" | 10,000.0000 |
10000.23 | "0,0" | 10,000 |
10000.23 | "+0,0" | +10,000 |
Currency
Number | Format | String |
---|---|---|
1000.234 | "$0,0.00" | $1,000.23 |
1000.2 | "0,0[.]00 $" | 1,000.20 $ |
Bytes
Number | Format | String |
---|---|---|
100 | "0b" | 100B |
2048 | "0 b" | 2 KB |
Percentages
Number | Format | String |
---|---|---|
1 | "0%" | 100% |
0.974878234 | "0.000%" | 97.488% |
Time
Number | Format | String |
---|---|---|
25 | "00:00:00" | 0:00:25 |
238 | "00:00:00" | 0:03:58 |
布爾值代表“真”和“假”兩個(gè)狀態(tài)?!罢妗庇藐P(guān)鍵字true表示,“假”用關(guān)鍵字false表示。布爾值只有這兩個(gè)值。如果JavaScript預(yù)期某個(gè)位置應(yīng)該是布爾值,會(huì)將該位置上現(xiàn)有的值自動(dòng)轉(zhuǎn)為布爾值。轉(zhuǎn)換規(guī)則是除了下面六個(gè)值被轉(zhuǎn)為false,其他值都視為true。
undefined
null
false
0
NaN
""(空字符串)
類型轉(zhuǎn)換所有對(duì)象的布爾值都是true,甚至連false對(duì)應(yīng)的布爾對(duì)象也是true。
Boolean(new Boolean(false)) // true空類型
JavaScript中常見(jiàn)的空類型為undefined與null,不過(guò)typeof undefined === ‘undefined’ 而 typeof null === ‘object’。
null表示"沒(méi)有對(duì)象",即該處不應(yīng)該有值。典型用法是:
作為函數(shù)的參數(shù),表示該函數(shù)的參數(shù)是對(duì)象。
作為對(duì)象原型鏈的終點(diǎn)。
undefined表示"缺少值",就是此處應(yīng)該有一個(gè)值,但是還未定義。典型用法是:
變量被聲明了,但沒(méi)有賦值時(shí),就等于undefined。
調(diào)用函數(shù)時(shí),應(yīng)該提供的參數(shù)沒(méi)有提供,該參數(shù)等于undefined。
對(duì)象沒(méi)有賦值的屬性,該屬性的值為undefined。
函數(shù)沒(méi)有返回值時(shí),默認(rèn)返回undefined。
SymbolsSymbols是JavaScript的第七種原始類型,它代指一個(gè)全局唯一的不可變對(duì)象。如果需要?jiǎng)?chuàng)建一個(gè)Symbol對(duì)象,則需要調(diào)用Symbol函數(shù):
var sym1 = Symbol(); var sym2 = Symbol("foo"); var sym3 = Symbol("foo");
如上的代碼會(huì)創(chuàng)建三個(gè)新的符號(hào),注意,雖然Symbol使用了”foo”這個(gè)字符串作為輸入對(duì)象,但是每次會(huì)創(chuàng)建一個(gè)新的符號(hào):
Symbol("foo") === Symbol("foo"); // false
確切地說(shuō),symbol與其它類型并不完全相像。symbol被創(chuàng)建后就不可變更,你不能為它設(shè)置屬性(在嚴(yán)格模式下嘗試設(shè)置屬性會(huì)得到TypeError的錯(cuò)誤)。他們可以用作屬性名稱,這些性質(zhì)與字符串類似。
另一方面,每一個(gè)symbol都獨(dú)一無(wú)二,不與其它symbol等同,即使二者有相同的描述也不相等;你可以輕松地創(chuàng)建一個(gè)新的symbol。這些性質(zhì)與對(duì)象類似。
ES6中的symbol與Lisp和Ruby這些語(yǔ)言中更傳統(tǒng)的symbol類似,但不像它們集成得那么緊密。在Lisp中,所有的標(biāo)識(shí)符都是symbol;在JS中,標(biāo)識(shí)符和大多數(shù)的屬性鍵仍然是字符串,symbol只是一個(gè)額外的選項(xiàng)。
關(guān)于symbol的忠告:symbol不能被自動(dòng)轉(zhuǎn)換為字符串,這和語(yǔ)言中的其它類型不同。嘗試拼接symbol與字符串將得到TypeError錯(cuò)誤。
> var sym = Symbol("<3"); > "your symbol is " + sym // TypeError: can"t convert symbol to string > `your symbol is ${sym}` // TypeError: can"t convert symbol to string
有三種獲取symbol的方法。
調(diào)用Symbol()。正如我們上文中所討論的,這種方式每次調(diào)用都會(huì)返回一個(gè)新的唯一symbol。
調(diào)用Symbol.for(string)。這種方式會(huì)訪問(wèn)symbol注冊(cè)表,其中存儲(chǔ)了已經(jīng)存在的一系列symbol。這種方式與通過(guò)Symbol()定義的獨(dú)立symbol不同,symbol注冊(cè)表中的symbol是共享的。如果你連續(xù)三十次調(diào)用Symbol.for("cat"),每次都會(huì)返回相同的symbol。注冊(cè)表非常有用,在多個(gè)web頁(yè)面或同一個(gè)web頁(yè)面的多個(gè)模塊中經(jīng)常需要共享一個(gè)symbol。
使用標(biāo)準(zhǔn)定義的symbol,例如:Symbol.iterator。標(biāo)準(zhǔn)根據(jù)一些特殊用途定義了少許的幾個(gè)symbol。
字符串類型 創(chuàng)建增刪 插值ES6中開(kāi)始支持較為復(fù)雜的模板字符串方式:
// Basic literal string creation `In JavaScript " " is a line-feed.` // Multiline strings `In JavaScript this is not legal.` // String interpolation var name = "Bob", time = "today"; `Hello ${name}, how are you ${time}?` // Construct an HTTP request prefix is used to interpret the replacements and construction GET`http://foo.org/bar?a=${a}&b=$ Content-Type: application/json X-Credentials: ${credentials} { "foo": ${foo}, "bar": ${bar}}`(myOnReadyStateChangeHandler);隨機(jī)字符串 UUID
node-uuid
類型編碼 類型轉(zhuǎn)換使用String函數(shù),可以將任意類型的值轉(zhuǎn)化成字符串。規(guī)則如下:
數(shù)值:轉(zhuǎn)為相應(yīng)的字符串。
字符串:轉(zhuǎn)換后還是原來(lái)的值。
布爾值:true轉(zhuǎn)為“true”,false轉(zhuǎn)為“false”。
undefined:轉(zhuǎn)為“undefined”。
null:轉(zhuǎn)為“null”。
而對(duì)于較復(fù)雜一點(diǎn)的對(duì)象類型,轉(zhuǎn)換規(guī)則如下:
先調(diào)用toString方法,如果toString方法返回的是原始類型的值,則對(duì)該值使用String方法,不再進(jìn)行以下步驟。
如果toString方法返回的是復(fù)合類型的值,再調(diào)用valueOf方法,如果valueOf方法返回的是原始類型的值,則對(duì)該值使用String方法,不再進(jìn)行以下步驟。
如果valueOf方法返回的是復(fù)合類型的值,則報(bào)錯(cuò)。
HTML編碼function html_encode(str) { var s = ""; if (str.length == 0) return ""; s = str.replace(/&/g, ">"); s = s.replace(//g, ">"); s = s.replace(/ /g, " "); s = s.replace(/"/g, "'"); s = s.replace(/"/g, """); s = s.replace(/ /g, "其他操作 Reverse
"); return s; } function html_decode(str) { var s = ""; if (str.length == 0) return ""; s = str.replace(/>/g, "&"); s = s.replace(//g, ">"); s = s.replace(/ /g, " "); s = s.replace(/'/g, """); s = s.replace(/"/g, """); s = s.replace(/
/g, " "); return s; }
str.split("").reverse().join("");Date Time Built-in:Date
根據(jù)毫秒計(jì)算對(duì)應(yīng)的天/時(shí)/分/秒
var left_time = ; function GetRTime(){ //var NowTime = new Date(); //var nMS = startTime.getTime() - NowTime.getTime() left_time = left_time - 1000; var nMS = left_time; var nD = Math.floor(nMS/(1000 * 60 * 60 * 24)); var nH = Math.floor(nMS/(1000*60*60)) % 24; var nM = Math.floor(nMS/(1000*60)) % 60; var nS = Math.floor(nMS/1000) % 60; if (nMS < 0){ }else{ } }Moment:JS的第三方時(shí)間庫(kù) Format
moment().format("MMMM Do YYYY, h:mm:ss a"); // August 26th 2015, 9:13:04 pm moment().format("ffffdd"); // Wednesday moment().format("MMM Do YY"); // Aug 26th 15 moment().format("YYYY [escaped] YYYY"); // 2015 escaped 2015 moment().format(); // 2015-08-26T21:13:04+08:00 var dateString = moment.unix(value).format("MM/DD/YYYY");
如果需要顯示本地化時(shí)間,需要引入locale目錄下對(duì)應(yīng)文件,并且使用moment.locale(String);進(jìn)行設(shè)置。另外注意,Unix時(shí)間戳指的是
Difference&&Duration:時(shí)間差var a = moment([2007, 0, 29]); var b = moment([2007, 0, 28]); a.diff(b) // 86400000 milliseconds a.diff(b, "days") // 1
如果需要將duration格式化為較好的顯示,可以參考moment-duration-format。
TimeZone(時(shí)間本地化)Indexed Collection ArrayCss-Tricks:本地化時(shí)間
在JavaScript中,Array是一個(gè)全局的對(duì)象可以用來(lái)創(chuàng)建數(shù)組,是一個(gè)高級(jí)別的有點(diǎn)類似于列表的集合??梢灾苯邮褂?b>Array.length來(lái)獲取某個(gè)數(shù)組的長(zhǎng)度。
創(chuàng)建增刪JavaScript創(chuàng)建新的數(shù)組,可以采用如下方式:
arr = [] arr = new Array() arr = new Array([PreSize]) arr = [] arr[1] = 1 // arr = [undefined , 1] 對(duì)于不存在的自動(dòng)賦值為undefined復(fù)制
slice() 方法把數(shù)組中一部分的淺復(fù)制(shallow copy)存入一個(gè)新的數(shù)組對(duì)象中,并返回這個(gè)新的數(shù)組。array.slice(begin[, end]).
slice會(huì)提取原數(shù)組中索引從 begin 到 end 的所有元素(包含begin,但不包含end)。
slice(1,4) 提取原數(shù)組中的第二個(gè)元素開(kāi)始直到第四個(gè)元素的所有元素 (索引為 1, 2, 3的元素)。
例子:返回?cái)?shù)組中的一部分
// Our good friend the citrus from fruits example var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"]; var citrus = fruits.slice(1, 3); // puts --> ["Orange","Lemon"]
例子:使用 slice
在下例中, slice從`myCar中創(chuàng)建了一個(gè)新數(shù)組`newCar.兩個(gè)數(shù)組都包含了一個(gè)myHonda對(duì)象的引用. 當(dāng)myHonda的color屬性改變?yōu)閜urple, 則兩個(gè)數(shù)組中的對(duì)應(yīng)元素都會(huì)隨之改變.
// 使用slice方法從myCar中創(chuàng)建一個(gè)newCar. var myHonda = { color: "red", wheels: 4, engine: { cylinders: 4, size: 2.2 } }; var myCar = [myHonda, 2, "cherry condition", "purchased 1997"]; var newCar = myCar.slice(0, 2); // 輸出myCar, newCar,以及各自的myHonda對(duì)象引用的color屬性. print("myCar = " + myCar.toSource()); print("newCar = " + newCar.toSource()); print("myCar[0].color = " + myCar[0].color); print("newCar[0].color = " + newCar[0].color); // 改變myHonda對(duì)象的color屬性. myHonda.color = "purple"; print("The new color of my Honda is " + myHonda.color); //輸出myCar, newCar中各自的myHonda對(duì)象引用的color屬性. print("myCar[0].color = " + myCar[0].color); print("newCar[0].color = " + newCar[0].color);
上述代碼輸出:
myCar = [{color:"red", wheels:4, engine:{cylinders:4, size:2.2}}, 2, "cherry condition", "purchased 1997"] newCar = [{color:"red", wheels:4, engine:{cylinders:4, size:2.2}}, 2] myCar[0].color = red newCar[0].color = red The new color of my Honda is purple myCar[0].color = purple newCar[0].color = purple
類數(shù)組(Array-like)對(duì)象
slice 方法可以用來(lái)將一個(gè)類數(shù)組(Array-like)對(duì)象/集合轉(zhuǎn)換成一個(gè)數(shù)組。你只需將該方法綁定到這個(gè)對(duì)象上。下述代碼中 list 函數(shù)中的 arguments 就是一個(gè)類數(shù)組對(duì)象。
function list() { return Array.prototype.slice.call(arguments); } var list1 = list(1, 2, 3); // [1, 2, 3]
除了使用 Array.prototype.slice.call(arguments),你也可以簡(jiǎn)單的使用 [].slice.call(arguments) 來(lái)代替。另外,你可以使用 bind 來(lái)簡(jiǎn)化該過(guò)程。
var unboundSlice = Array.prototype.slice; var slice = Function.prototype.call.bind(unboundSlice); function list() { return slice(arguments); } var list1 = list(1, 2, 3); // [1, 2, 3]插入刪除
JavaScript的Array支持從頭部插入移除,從尾部插入移除等多種方式:
var fruits = ["Apple", "Banana"]; var newLength = fruits.push("Orange");//從尾部插入,返回的數(shù)組長(zhǎng)度 // ["Apple", "Banana", "Orange"] var last = fruits.pop(); // remove Orange (from the end),返回刪除的對(duì)象 // ["Apple", "Banana"]; var first = fruits.shift(); // remove Apple from the front // ["Banana"]; var newLength = fruits.unshift("Strawberry") // add to the front // ["Strawberry", "Banana"];遍歷索引 存在性判斷
var array = [1, 2, 3]; array.includes(1); // → true反向索引
如果在數(shù)組中需要反向索引某個(gè)元素的位置,可以使用indexOf方法
fruits.push("Mango"); // ["Strawberry", "Banana", "Mango"] var pos = fruits.indexOf("Banana"); // 1 var array = [2, 9, 9, 4, 3, 6]; var result = array.lastIndexOf(9); console.log(result); // output: 2
如果存儲(chǔ)的是復(fù)雜的對(duì)象,則可以使用find方法,返回?cái)?shù)組中滿足測(cè)試條件的一個(gè)元素,如果沒(méi)有滿足條件的元素,則返回 undefined。
_.find(users, function(o) { return o.age < 40; }); // output: object for "barney" // Native var users = [ { "user": "barney", "age": 36, "active": true }, { "user": "fred", "age": 40, "active": false }, { "user": "pebbles", "age": 1, "active": true } ]; users.find(function(o) { return o.age < 40; }); // output: object for "barney" var index = users.findIndex(function(o) { return o.age >= 40; }); console.log(index); // output: 1遍歷
fruits.forEach(function (item, index, array) { console.log(item, index); }); // Apple 0 // Banana 1Set:集合
集合也是一種常見(jiàn)的數(shù)據(jù)結(jié)構(gòu),在ES6中添加了對(duì)于集合的支持,其基本用法如下:
// Sets var s = new Set(); s.add("hello").add("goodbye").add("hello"); s.size === 2; s.has("hello") === true;WeakSet
WeakSet提供了一種自回收的存儲(chǔ)方式:
// Weak Sets var ws = new WeakSet(); ws.add({ data: 42 }); // Because the added object has no other references, it will not be held in the set序列操作 map
將某個(gè)列表中的元素映射到新的列表中。
// Native var array1 = [1, 2, 3]; var array2 = array1.map(function(value, index) { return value*2; }); console.log(array2); // output: [2, 4, 6]reduce
var array = [0, 1, 2, 3, 4]; var result = array.reduce(function (previousValue, currentValue, currentIndex, array) { return previousValue + currentValue; }); console.log(result); // output: 10 //reduceRight,正好方向相反 var array = [0, 1, 2, 3, 4]; var result = array.reduceRight(function (previousValue, currentValue, currentIndex, array) { return previousValue - currentValue; }); console.log(result); // output: -2filter
// Native function isBigEnough(value) { return value >= 10; } var array = [12, 5, 8, 130, 44]; var filtered = array.filter(isBigEnough); console.log(filtered); // output: [12, 130, 44]Keyed Collections Object
Maps,Sets And Iterators in JavaScript
javascript-properties
JavaScript中Object是一個(gè)混合了類似于Dictionary與Class的用法,基本上來(lái)說(shuō)也是一種鍵值類型。其中鍵的類型主要包含三種:
Identifier:包含任何有效地標(biāo)識(shí)符,包括了ES的保留關(guān)鍵字。
字符串:single (") or double (") quotes. "foo", "bar","qu"ux", "" (the empty string), and "Ich u2665 BxFCcher" are all valid string literals.
數(shù)字:decimal literal (e.g. 0, 123, 123., .123, 1.23, 1e23, 1E-23, 1e+23, 12, but not 01, +123 or -123) or a hex integer literal (0[xX][0-9a-fA-F]+ in regex, e.g. 0xFFFF, 0X123,0xaBcD).
var object = { // `abc` is a valid identifier; no quotes are needed abc: 1, // `123` is a numeric literal; no quotes are needed 123: 2, // `012` is an octal literal with value `10` and thus isn’t allowed in strict mode; but if you insist on using it, quotes aren’t needed 012: 3, // `π` is a valid identifier; no quotes are needed π: Math.PI, // `var` is a valid identifier name (although it’s a reserved word); no quotes are needed var: 4, // `foo bar` is not a valid identifier name; quotes are required "foo bar": 5, // `foo-bar` is not a valid identifier name; quotes are required "foo-bar": 6, // the empty string is not a valid identifier name; quotes are required "": 7 };
注意,與object不同的是,JSON 只允許用雙引號(hào) (") 包裹的字符串作為鍵名。而如果要根據(jù)鍵名進(jìn)行索引的話,可以使用方括號(hào),這種方式對(duì)于三種鍵值皆有效:
object["abc"]; // 1
有時(shí)候也可以使用點(diǎn)操作符,不過(guò)這種方式只可以被用于鍵為有效地Identifier情況:
object.abc; // 1
如果需要獲取所有的鍵名的話,可以使用Object.keys方法:
注意,所有的Object的方法只能用Object.methodName方式調(diào)用
// Native var result2 = Object.keys({one: 1, two: 2, three: 3}); console.log(result2); // output: ["one", "two", "three"] //也可以等效獲取大小 var result2 = Object.keys({one: 1, two: 2, three: 3}).length; console.log(result2); // output: 3創(chuàng)建添加 Object.create() :創(chuàng)建一個(gè)擁有指定原型和若干個(gè)指定屬性的對(duì)象。
其基本語(yǔ)法為:
Object.create(proto, { propertiesObject })
這里需要注意的是,propertiesObject不是一個(gè)簡(jiǎn)單的鍵值類型,而是有固定格式的object。
var o; // 創(chuàng)建一個(gè)原型為null的空對(duì)象 o = Object.create(null); o = {}; // 以字面量方式創(chuàng)建的空對(duì)象就相當(dāng)于: o = Object.create(Object.prototype); o = Object.create(Object.prototype, { // foo會(huì)成為所創(chuàng)建對(duì)象的數(shù)據(jù)屬性 foo: { writable:true, configurable:true, value: "hello" }, // bar會(huì)成為所創(chuàng)建對(duì)象的訪問(wèn)器屬性 bar: { configurable: false, get: function() { return 10 }, set: function(value) { console.log("Setting `o.bar` to", value) } }}) function Constructor(){} o = new Constructor(); // 上面的一句就相當(dāng)于: o = Object.create(Constructor.prototype); // 當(dāng)然,如果在Constructor函數(shù)中有一些初始化代碼,Object.create不能執(zhí)行那些代碼 // 創(chuàng)建一個(gè)以另一個(gè)空對(duì)象為原型,且擁有一個(gè)屬性p的對(duì)象 o = Object.create({}, { p: { value: 42 } }) // 省略了的屬性特性默認(rèn)為false,所以屬性p是不可寫,不可枚舉,不可配置的: o.p = 24 o.p //42 o.q = 12 for (var prop in o) { console.log(prop) } //"q" delete o.p //false //創(chuàng)建一個(gè)可寫的,可枚舉的,可配置的屬性p o2 = Object.create({}, { p: { value: 42, writable: true, enumerable: true, configurable: true } });Object.assign:一層淺復(fù)制
Object.assign() 方法可以把任意多個(gè)的源對(duì)象所擁有的自身可枚舉屬性拷貝給目標(biāo)對(duì)象,然后返回目標(biāo)對(duì)象。Object.assign 方法只會(huì)拷貝源對(duì)象自身的并且可枚舉的屬性到目標(biāo)對(duì)象身上。注意,對(duì)于訪問(wèn)器屬性,該方法會(huì)執(zhí)行那個(gè)訪問(wèn)器屬性的 getter 函數(shù),然后把得到的值拷貝給目標(biāo)對(duì)象,如果你想拷貝訪問(wèn)器屬性本身,請(qǐng)使用 Object.getOwnPropertyDescriptor() 和Object.defineProperties() 方法。
注意,字符串類型和 symbol 類型的屬性都會(huì)被拷貝。
注意,在屬性拷貝過(guò)程中可能會(huì)產(chǎn)生異常,比如目標(biāo)對(duì)象的某個(gè)只讀屬性和源對(duì)象的某個(gè)屬性同名,這時(shí)該方法會(huì)拋出一個(gè) TypeError 異常,拷貝過(guò)程中斷,已經(jīng)拷貝成功的屬性不會(huì)受到影響,還未拷貝的屬性將不會(huì)再被拷貝。
注意, Object.assign 會(huì)跳過(guò)那些值為 null 或 undefined 的源對(duì)象。
Object.assign(target, ...sources)
例子:淺拷貝一個(gè)對(duì)象
var obj = { a: 1 }; var copy = Object.assign({}, obj); console.log(copy); // { a: 1 }
例子:合并若干個(gè)對(duì)象
var o1 = { a: 1 }; var o2 = { b: 2 }; var o3 = { c: 3 }; var obj = Object.assign(o1, o2, o3); console.log(obj); // { a: 1, b: 2, c: 3 } console.log(o1); // { a: 1, b: 2, c: 3 }, 注意目標(biāo)對(duì)象自身也會(huì)改變。
例子:拷貝 symbol 類型的屬性
var o1 = { a: 1 }; var o2 = { [Symbol("foo")]: 2 }; var obj = Object.assign({}, o1, o2); console.log(obj); // { a: 1, [Symbol("foo")]: 2 }
例子:繼承屬性和不可枚舉屬性是不能拷貝的
var obj = Object.create({foo: 1}, { // foo 是個(gè)繼承屬性。 bar: { value: 2 // bar 是個(gè)不可枚舉屬性。 }, baz: { value: 3, enumerable: true // baz 是個(gè)自身可枚舉屬性。 } }); var copy = Object.assign({}, obj); console.log(copy); // { baz: 3 }
例子:原始值會(huì)被隱式轉(zhuǎn)換成其包裝對(duì)象
var v1 = "123"; var v2 = true; var v3 = 10; var v4 = Symbol("foo") var obj = Object.assign({}, v1, null, v2, undefined, v3, v4); // 源對(duì)象如果是原始值,會(huì)被自動(dòng)轉(zhuǎn)換成它們的包裝對(duì)象, // 而 null 和 undefined 這兩種原始值會(huì)被完全忽略。 // 注意,只有字符串的包裝對(duì)象才有可能有自身可枚舉屬性。 console.log(obj); // { "0": "1", "1": "2", "2": "3" }
例子:拷貝屬性過(guò)程中發(fā)生異常
var target = Object.defineProperty({}, "foo", { value: 1, writeable: false }); // target 的 foo 屬性是個(gè)只讀屬性。 Object.assign(target, {bar: 2}, {foo2: 3, foo: 3, foo3: 3}, {baz: 4}); // TypeError: "foo" is read-only // 注意這個(gè)異常是在拷貝第二個(gè)源對(duì)象的第二個(gè)屬性時(shí)發(fā)生的。 console.log(target.bar); // 2,說(shuō)明第一個(gè)源對(duì)象拷貝成功了。 console.log(target.foo2); // 3,說(shuō)明第二個(gè)源對(duì)象的第一個(gè)屬性也拷貝成功了。 console.log(target.foo); // 1,只讀屬性不能被覆蓋,所以第二個(gè)源對(duì)象的第二個(gè)屬性拷貝失敗了。 console.log(target.foo3); // undefined,異常之后 assign 方法就退出了,第三個(gè)屬性是不會(huì)被拷貝到的。 console.log(target.baz); // undefined,第三個(gè)源對(duì)象更是不會(huì)被拷貝到的。
不過(guò)需要注意的是,assign是淺拷貝,或者說(shuō),它是一級(jí)深拷貝,舉兩個(gè)例子說(shuō)明:
const defaultOpt = { title: { text: "hello world", subtext: "It"s my world." } }; const opt = Object.assign({}, defaultOpt, { title: { subtext: "Yes, your world." } }); console.log(opt); // 預(yù)期結(jié)果 { title: { text: "hello world", subtext: "Yes, your world." } } // 實(shí)際結(jié)果 { title: { subtext: "Yes, your world." } }
上面這個(gè)例子中,對(duì)于對(duì)象的一級(jí)子元素而言,只會(huì)替換引用,而不會(huì)動(dòng)態(tài)的添加內(nèi)容。那么,其實(shí)assign并沒(méi)有解決對(duì)象的引用混亂問(wèn)題,參考下下面這個(gè)例子:
const defaultOpt = { title: { text: "hello world", subtext: "It"s my world." } }; const opt1 = Object.assign({}, defaultOpt); const opt2 = Object.assign({}, defaultOpt); opt2.title.subtext = "Yes, your world."; console.log("opt1:"); console.log(opt1); console.log("opt2:"); console.log(opt2); // 結(jié)果 opt1: { title: { text: "hello world", subtext: "Yes, your world." } } opt2: { title: { text: "hello world", subtext: "Yes, your world." } }Map 創(chuàng)建增刪
var map = new Map(); map.set("foo", "bar"); console.log(map.get("foo")); //logs "bar" var animalSounds = new Map(); animalSounds.set("dog", "woof"); animalSounds.set("cat", "meow"); animalSounds.set("frog", "ribbit"); console.log(animalSounds.size); //logs 3 console.log(animalSounds.has("dog")); //logs true animalSounds.delete("dog"); console.log(animalSounds.size); //logs 2 console.log(animalSounds.has("dog")); //logs false animalSounds.clear(); console.log(animalSounds.size); //logs 0索引遍歷
usersMap = new Map(); usersMap.set(1, "sally"); usersMap.set(2, "bob"); usersMap.set(3, "jane"); console.log(usersMap.get(1)); //logs "sally" usersMap.forEach(function (username, userId) { console.log(userId, typeof userId); //logs 1..3, "number" if (userId === 1) { console.log("We found sally."); } }); //如果用for...of方式遍歷,每次返回的是一個(gè)Array for (data of usersMap) { console.log(data);//Array [1,"sally"] }
Map的鍵的類型可以是object、NaN等等。
var obj, map; map = new Map(); obj = {foo: "bar"}; map.set(obj, "foobar"); obj.newProp = "stuff"; console.log(map.has(obj)); //logs true console.log(map.get(obj)); //logs "foobar"Immutable.js
FaceBook-Immutable
Immutable 詳解及 React 中實(shí)踐
Immutable 對(duì)象一旦被創(chuàng)建之后即不可再更改,這樣可以使得應(yīng)用開(kāi)發(fā)工作變得簡(jiǎn)化,不再需要大量的保護(hù)性拷貝,使用簡(jiǎn)單的邏輯控制即可以保證內(nèi)存控制與變化檢測(cè)。Immutable.js雖然和React同期出現(xiàn)且跟React配合很爽,但它可不是React工具集里的(它的光芒被掩蓋了),它是一個(gè)完全獨(dú)立的庫(kù),無(wú)論基于什么框架都可以用它。意義在于它彌補(bǔ)了Javascript沒(méi)有不可變數(shù)據(jù)結(jié)構(gòu)的問(wèn)題。不可變數(shù)據(jù)結(jié)構(gòu)是函數(shù)式編程中必備的。前端工程師被OOP洗腦太久了,組件根本上就是函數(shù)用法,F(xiàn)P的特點(diǎn)更適用于前端開(kāi)發(fā)。
Javascript中對(duì)象都是參考類型,也就是a={a:1}; b=a; b.a=10;你發(fā)現(xiàn)a.a也變成10了??勺兊暮锰幨枪?jié)省內(nèi)存或是利用可變性做一些事情,但是,在復(fù)雜的開(kāi)發(fā)中它的副作用遠(yuǎn)比好處大的多。于是才有了淺copy和深copy,就是為了解決這個(gè)問(wèn)題。舉個(gè)常見(jiàn)例子:
var defaultConfig = { /* 默認(rèn)值 */}; var config = $.extend({}, defaultConfig, initConfig); // jQuery用法。initConfig是自定義值 var config = $.extend(true, {}, defaultConfig, initConfig); // 如果對(duì)象是多層的,就用到deep-copy了
而
var stateV1 = Immutable.fromJS({ users: [ { name: "Foo" }, { name: "Bar" } ] }); var stateV2 = stateV1.updateIn(["users", 1], function () { return Immutable.fromJS({ name: "Barbar" }); }); stateV1 === stateV2; // false stateV1.getIn(["users", 0]) === stateV2.getIn(["users", 0]); // true stateV1.getIn(["users", 1]) === stateV2.getIn(["users", 1]); // false
如上,我們可以使用===來(lái)通過(guò)引用來(lái)比較對(duì)象,這意味著我們能夠方便快速的進(jìn)行對(duì)象比較,并且它能夠和React中的PureRenderMixin 兼容?;诖耍覀兛梢栽谡麄€(gè)應(yīng)用構(gòu)建中使用Immutable.js。也就是說(shuō),我們的Flux Store應(yīng)該是一個(gè)具有不變性的對(duì)象,并且我們通過(guò) 將具有不變性的數(shù)據(jù)作為屬性傳遞給我們的應(yīng)用程序。
創(chuàng)建與判斷如果要?jiǎng)?chuàng)建Immutable對(duì)象,使用fromJS方法既可以將簡(jiǎn)單的JS中的objects與arrays轉(zhuǎn)化為不可變的Maps與Lists
fromJS(json: any, reviver?: (k: any, v: Iterable) => any): any
如果reviver這個(gè)屬性被提供了,那么它會(huì)傳入一個(gè)Seq對(duì)象并且被循環(huán)調(diào)用,對(duì)于頂層對(duì)象,它的默認(rèn)的鍵為""。
Immutable.fromJS({a: {b: [10, 20, 30]}, c: 40}, function (key, value) { var isIndexed = Immutable.Iterable.isIndexed(value); return isIndexed ? value.toList() : value.toOrderedMap(); }); // true, "b", {b: [10, 20, 30]} // false, "a", {a: {b: [10, 20, 30]}, c: 40} // false, "", {"": {a: {b: [10, 20, 30]}, c: 40}}
對(duì)于轉(zhuǎn)化而來(lái)的Immutable對(duì)象,可以通過(guò)Iterable.is*方法來(lái)判斷其是列表還是映射或者其他數(shù)據(jù)類型。
List 創(chuàng)建增刪 更新 刪除 遍歷索引 Map 創(chuàng)建增刪 更新要更新Map中的某個(gè)元素值,需要調(diào)用updateIn方法,該方法會(huì)根據(jù)傳入的keyPath尋找到該值,然后進(jìn)行安全修正并返回一個(gè)新的對(duì)象。如果keyPath值并不存在,那么返回的Map對(duì)象會(huì)自動(dòng)創(chuàng)建該鍵,如果KeyPath沒(méi)有提供指定值,那么會(huì)自動(dòng)調(diào)用notSetValue或者賦值為undefined
updateIn(keyPath: Array, updater: (value: any) => any): Map updateIn( keyPath: Array , notSetValue: any, updater: (value: any) => any ): Map updateIn(keyPath: Iterable , updater: (value: any) => any): Map updateIn( keyPath: Iterable , notSetValue: any, updater: (value: any) => any ): Map
var data = Immutable.fromJS({ a: { b: { c: 10 } } }); data = data.updateIn(["a", "b", "c"], val => val * 2); // { a: { b: { c: 20 } } }刪除
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/78719.html
摘要:模板語(yǔ)法四種詞法定義二空白符號(hào)空白符號(hào)分類或稱是,是縮進(jìn)符,字符串中寫的。注意換行符會(huì)影響的兩個(gè)重要語(yǔ)法特性自動(dòng)插入分號(hào)和規(guī)則。 筆記說(shuō)明 重學(xué)前端是程劭非(winter)【前手機(jī)淘寶前端負(fù)責(zé)人】在極客時(shí)間開(kāi)的一個(gè)專欄,每天10分鐘,重構(gòu)你的前端知識(shí)體系,筆者主要整理學(xué)習(xí)過(guò)程的一些要點(diǎn)筆記以及感悟,完整的可以加入winter的專欄學(xué)習(xí)【原文有winter的語(yǔ)音】,如有侵權(quán)請(qǐng)聯(lián)系我,郵箱...
摘要:模板語(yǔ)法四種詞法定義二空白符號(hào)空白符號(hào)分類或稱是,是縮進(jìn)符,字符串中寫的。注意換行符會(huì)影響的兩個(gè)重要語(yǔ)法特性自動(dòng)插入分號(hào)和規(guī)則。 筆記說(shuō)明 重學(xué)前端是程劭非(winter)【前手機(jī)淘寶前端負(fù)責(zé)人】在極客時(shí)間開(kāi)的一個(gè)專欄,每天10分鐘,重構(gòu)你的前端知識(shí)體系,筆者主要整理學(xué)習(xí)過(guò)程的一些要點(diǎn)筆記以及感悟,完整的可以加入winter的專欄學(xué)習(xí)【原文有winter的語(yǔ)音】,如有侵權(quán)請(qǐng)聯(lián)系我,郵箱...
摘要:模板語(yǔ)法四種詞法定義二空白符號(hào)空白符號(hào)分類或稱是,是縮進(jìn)符,字符串中寫的。注意換行符會(huì)影響的兩個(gè)重要語(yǔ)法特性自動(dòng)插入分號(hào)和規(guī)則。 筆記說(shuō)明 重學(xué)前端是程劭非(winter)【前手機(jī)淘寶前端負(fù)責(zé)人】在極客時(shí)間開(kāi)的一個(gè)專欄,每天10分鐘,重構(gòu)你的前端知識(shí)體系,筆者主要整理學(xué)習(xí)過(guò)程的一些要點(diǎn)筆記以及感悟,完整的可以加入winter的專欄學(xué)習(xí)【原文有winter的語(yǔ)音】,如有侵權(quán)請(qǐng)聯(lián)系我,郵箱...
閱讀 918·2021-11-22 13:53
閱讀 2543·2021-10-15 09:40
閱讀 1013·2021-10-14 09:42
閱讀 3589·2021-09-22 15:59
閱讀 902·2021-09-02 09:47
閱讀 2408·2019-08-30 15:54
閱讀 1448·2019-08-29 17:14
閱讀 412·2019-08-29 15:15