以自己作為客戶端RD的視角赵哲,列舉了一些在實際使用中比較常見,而又比較陌生的語法(主要集中在ES6的特性上)儿奶,做好一些鋪墊和基礎(chǔ)喜滨。
介紹
ECMAScript 6(以下簡稱ES6)是JavaScript語言的下一代標(biāo)準(zhǔn)焚廊。因為當(dāng)前版本的ES6是在2015年發(fā)布的,所以又稱ECMAScript 2015习劫。在 ES5 的基礎(chǔ)上新增了很多特性咆瘟,完善了自身結(jié)構(gòu),解決了很多問題诽里,更容易使用了袒餐。
TS - TypeScript,有類型的 JavaScript谤狡,通過增加靜態(tài)類型檢查來實現(xiàn)“強類型”特性灸眼,是 JavaScript 的超集,也可以通過被編譯成低版本的 ES3 兼容所有運行環(huán)境豌汇。
TS 出現(xiàn)比ES6早幢炸,最初 TS 中添加了很多語法規(guī)范和特性泄隔,但隨著 ES 的版本迭代拒贱,TS 的很多語法特性都被追平,目前集中在強類型上佛嬉,對于客戶端或熟悉使用編譯型語言的同學(xué)來說逻澳,這種強類型模式比較熟悉,所以篇幅會比較小暖呕。
下面會先介紹 ES6斜做,在此基礎(chǔ)上,再介紹TS額外的部分湾揽。
ES6
一 變量聲明
之前: var
現(xiàn)在:let(變量) 和 const(常量)
var 問題:
1.var 全局作用域瓤逼,易出錯;let const 塊級作用域
{
let a = 10;
var b =20;
}
a //調(diào)用失敗 let 聲明的變量的為局部變量库物,只在{....}的塊作用域生效霸旗。
b //20 var 聲明的變量為全局變量,在全局作用域生效
// example 2
var s = "foo"
if (true) {
var s = "bar"
}
s // s=bar
2.const可定義常量
const a = 10;
a = 20; //再次賦值失敗 const創(chuàng)建的變量為常量戚揭,一旦聲明了就不能改變
二 解構(gòu)賦值
變量的解構(gòu)賦值為ES新推出的特性诱告,指的是ES6允許按照一定的模式,從數(shù)組或?qū)ο笾腥〕鲋得裆梗瑢ψ兞窟M行賦值精居。 如果解構(gòu)不成功,變量的值就等于undefined潜必。
# 數(shù)組解構(gòu)
let [a,b,c] = [1,2,3] 這種寫法稱為模式匹配靴姿,只要 “兩邊” 結(jié)構(gòu)一致即可賦值。
console.log(a) //1
console.log(b) //2
console.log(c) //3
# 部分解構(gòu)不成功
let [a磁滚,b] = [1]
console.log(a) //1
console.log(b) //undefined 部分解構(gòu)不成功
// 默認(rèn)值
let [a,b=3] = [1]
console.log(a) //1
console.log(b) //3
# 對象解構(gòu)
let node = {
sex:'fmale',
age:10
}
let {sex,age} = node;
console.log(sex) //fmale 對象解構(gòu)佛吓,對于內(nèi)置對象同樣可以。
console.log(age) //10
# 函數(shù)參數(shù)的解構(gòu)賦值
function add([x,y]){
return x + y;
}
let value = add([1,2,3,4,5,6])
value //3 函數(shù)的參數(shù)解構(gòu)賦值 形容 let [x,y] = [1,2,3,4,5,6]
# 數(shù)值的解構(gòu)賦值
let [a,b,c] = 123
console.log(a) //1 數(shù)值解構(gòu)
console.log(b) //2
console.log(c) //3
# 字符串的解構(gòu)賦值
let [a,b,c] = '123';
console.log(a) //1
console.log(b) //2
console.log(c) //3
//原則上 只要兩邊的結(jié)構(gòu)一致都可以進行解構(gòu)賦值。
三 函數(shù)
箭頭函數(shù)
去掉function辈毯,用箭頭鏈接方法體
- 有且僅有一個參數(shù)坝疼,()可以不寫
- 如果有且只一個語句,return 和 {}可以不寫
let a = function(x){
return x * 2
}
a(4) // 8
// 變化1
let a = (x)=>{
return x * 2
}
a(4) // 8
// 變化2
let a = x=>{
return x * 2
}
a(4) // 8
// 變化3
let a = x=> x * 2
a(4) // 8
// 作為回調(diào)谆沃,在入?yún)⒅泻啙嵄磉_
setTimeout(() => {
// to do
}, 500)
this
js 里 this 使用非常復(fù)雜钝凶,就不展開說。直接說結(jié)論:
普通函數(shù)里 this 在函數(shù)調(diào)用時才被賦值唁影,this 等于函數(shù)執(zhí)行時候的執(zhí)行環(huán)境耕陷;
使用箭頭函數(shù)時,this 等于定義時的環(huán)境据沈;
詳見:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions
四 參數(shù)擴展
打開參數(shù)
數(shù)組展開
var arr = [1, 2, 3];
var arr2 = [...arr]; // ...arr 等價 [1,2,3]
arr2.push(4);
console.log(arr2)// [1, 2, 3, 4]
json展開
let obj1 = {
foo: 'bar',
x: 42
};
let obj2 = {
foo: 'new bar',
y: 13
};
let clonedObj = { ...obj1 };
let mergedObj = { ...obj1, ...obj2 }; // merge 后加的參數(shù)會覆蓋先加入的參數(shù)
console.log(clonedObj) // {foo: "bar", x: 42}
console.log(mergedObj) // {foo: "new bar", x: 42, y: 13}
收集參數(shù)
函數(shù)的剩余參數(shù)
function add(a,...values){
var total = 0;
for(var val of values){
total +=val;
}
return total;
}
add(1,2,3,4,5); //2+3+4+5 = 14
五 數(shù)組的操作方法
這里記錄的很全: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array
挑幾個常見的說下:
map() 映射 一一對應(yīng)
reduce() 收集 出一個結(jié)果
filter() 過濾 留下一部分
foreach() 遍歷 每一個都訪問
let array = [1, 4, 9, 16];
// pass a function to map
let map1 = array.map(x => x * 2)
let map2 = array.reduce((x, y) => x + y)
let map3 = array.filter(x => x > 4)
let map4 = array.forEach(x => console.log(x))
console.log(map1);// expected output: Array [2, 8, 18, 32]
console.log(map2);// 30
console.log(map3);// [9, 16]
console.log(map4);// 1, 4, 9, 16
六 字符串模板
反單引號 `` 圍起來字符串哟沫,可以動態(tài)添加變量
# 模板字符串中 嵌入變量
let [a,b] = ['jack','Bob']
let text = `hello ${a},I'm $` // 美元符+花括號將變量替換到字符
text //hello jack, I'm Bob
# 模板字符串中進行邏輯運算
let [a,b] = [1,2]
let result = `${a} + $锌介 = ${a+b}`
result //1 + 2 = 3
七 JSON 序列化操作
調(diào)試的時候很常用嗜诀,有坑點單獨說下。
JSON.stringify()
JSON.parse() // 需要標(biāo)準(zhǔn)化的JSON
// 不是標(biāo)準(zhǔn)化json孔祸,key不是字符串
let json = {
a:'foo',
b:'bar',
c:100
}
JSON.stringify(json) //"{"a":"foo","b":"bar","c":100}"
let str = '{"a":"foo","b":"bar","c":100}'
// let str = "{'a':'foo','b':'bar','c':100}" key一定要有"雙引號"隆敢,反過來也不行
JSON.parse(str)
八 異步編程
異步操作,回調(diào)地獄
代碼塊
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
let user
// ajax get請求數(shù)據(jù)
$.get('https://api.github.com/users', data=>{
console.log('fetched all users')
user = data[0].login
// 數(shù)據(jù)校驗正確崔慧,再請求下一步
$.get(`https://api.github.com/users/${user}/repos`, data=>{
console.log('fetched all repos')
console.log(data)
})
})
</script>
promise
作用:進行統(tǒng)一的異步封裝
let promise = new Promise(function (resolve, reject) {
// 做一些異步操作
if(/*異步操作成功*/){
//該value傳入回調(diào)函數(shù)中
resolve(result);
}else{
//該error傳入回調(diào)函數(shù)
reject(error);
}
})
promise.then(result=>{
console.log(result)
}).catch(err => {
console.log(err)
}).finally(()=>{
// 最終執(zhí)行的代碼段
})
//其他
1.Promise.all(arry) // all 等待所有異步操作執(zhí)行完成 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
2.Promise.race(arry) // race 任一執(zhí)行完成后就結(jié)束 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/race
再看上面的回調(diào)地獄拂蝎,可以用階段性返回 promise 對象來解決循環(huán)嵌套
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.16.2/axios.min.js"></script>
<script>
axios.get('https://api.github.com/users') // 返回一個 Promise
.then(reponse => {
let username = reponse.data[0].login
// 解析正確返回下一個請求的Promise
return axios.get(`https://api.github.com/users/${username}/repos`)
})
.then(reponse => {
console.log(reponse.data)
})
.catch(err => {
console.log(err)
})
</script>
async/await
更直觀的語法,將異步變同步惶室,ES2017(es8)
async function myFetch() {
let reponse = await axios.get('https://api.github.com/users') // 返回一個 Promise
let username = reponse.data[0].login
let repos = await axios.get(`https://api.github.com/users/${username}/repos`)
// 操作 repos ...
}
async/await 原理:可以將函數(shù)執(zhí)行暫停温自,通過將函數(shù)切換成多個小函數(shù)來實現(xiàn)。
更多參考:https://developer.mozilla.org/zh-CN/docs/learn/JavaScript/%E5%BC%82%E6%AD%A5/Async_await
九 模塊
導(dǎo)出 export:獨立模塊的對象皇钞、函數(shù)悼泌、值是無法被其他文件訪問到的,如果要讓外部訪問到鹅士,需要使用 export 導(dǎo)出
相對的券躁,要使用其他模塊內(nèi)容,就需要導(dǎo)入 import 相關(guān)內(nèi)容
// module "my-module.js"
function cube(x) {// 函數(shù)
return x * x * x;
}
const foo = Math.PI + Math.SQRT2;// 常量
var graph = {
options: {
color:'white',
thickness:'2px'
},
draw: function() {
console.log('From graph draw function');
}
}
export { cube, foo, graph };
// --------------- another file ---------------
import { cube, foo, graph } from 'my-module.js';
graph.options = {
color:'blue',
thickness:'3px'
};
graph.draw();
console.log(cube(3)); // 27
console.log(foo); // 4.555806215962888
此外還有默認(rèn)導(dǎo)出掉盅,即我們在 vue 里常見的 export default 也拜,只是將當(dāng)前模塊做默認(rèn)導(dǎo)出,沒有其他特殊含義趾痘。
// module "my-module.js"
export default function cube(x) {
return x * x * x;
}
// --------------- another file ---------------
import cube from './my-module.js';
console.log(cube(3)); // 27
TS
列舉下實際開發(fā)中慢哈,常遇見的TS里有的,但是 ES6 所沒有的特性永票,總結(jié)下來就是:
- 類型(核心)
- 面向?qū)ο笤鰪?br> 這里只是簡單列舉卵贱,一些細節(jié)和JAVA或OC使用都類似滥沫,如果遇到報錯,再查文檔 https://www.tslang.cn/docs/handbook/basic-types.html 找找原因键俱,會比較好懂
一 類型
1.強類型
不同于大部分編譯型語言兰绣,TS 的類型是寫在變量名后面,通過冒號: 連接的
const name:String = "Hello World"
TypeScript 里也有現(xiàn)代語言都具備的類型推斷特性(Java要10以上的版本)编振,不需要每一個變量都聲明類型缀辩。
2.支持聯(lián)合類型
多種類型用豎線 | 連接,表示該變量可以是多種類型的
function padLeft(value: string, padding: string | number) {
// ...
}
function getSmallPet(): Fish | Bird {
// ...
}
3.元組
swift 里也有踪央,允許表示一個已知元素數(shù)量和類型的數(shù)組臀玄,各元素的類型不必相同。 比如畅蹂,你可以定義一對值分別為 string和number類型的元組健无。
let x: [string, number] = ['hello', 10];
4.枚舉
這個都懂
enum Color {Red, Green, Blue}
5.特殊類型
- any —— 表示任何類型
- void —— 表示沒有類型,用于修飾函數(shù)返回值類型液斜,作為變量類型時累贤,沒有什么用
- never —— 表示的是那些永不存在的值的類型,和 null 或 undefined 不同旗唁,他用來表示類型畦浓,而不是具體的值
6.函數(shù)類型
在基礎(chǔ)函數(shù)上,多了入?yún)㈩愋秃头祷刂殿愋?/p>
//函數(shù)類型(入?yún)⒌念愋图煲撸祷刂殿愋停?返回值類型
function(x: number, y: number): number {
// 函數(shù)體
return x + y;
};
聲明一個函數(shù)的變量 myAdd ,也需要指定這個函數(shù)的類型祷嘶,函數(shù)類型比較復(fù)雜點屎媳,分成入?yún)㈩愋秃头祷刂殿愋汀?br> (入?yún)?:入?yún)?類型, 入?yún)?:入?yún)?類型) => 返回值類型
代碼塊
// 變量名 函數(shù)類型(入?yún)⒌念愋停祷刂殿愋停? = 入?yún)⒌念愋停▊z number) 返回值類型 函數(shù)體
let myAdd: (x: number, y: number) => number = function(x: number, y: number): number { return x + y; };
// 定義太長了论巍,不寫烛谊,也可以通過推斷得出
let myAdd = function(x: number, y: number): number { return x + y; };
// 箭頭函數(shù)基本沒變,入?yún)⒓恿祟愋?let double = (e: number) => { return e * 2}
推斷文檔:https://www.tslang.cn/docs/handbook/type-inference.html
二 面向?qū)ο?/h2>
1.接口
這個JAVA開發(fā)太熟悉了嘉汰,但是在TS里丹禀,他更多的是用來創(chuàng)建 Model 數(shù)據(jù)模型
interface LabelledValue {
label: string;
}
function printLabel(labelledObj: LabelledValue) {
console.log(labelledObj.label);
}
加上可選,這種感覺就更明顯了
interface SquareConfig {
color?: string;
width?: number;
}
2.類的Field支持修飾符
public 鞋怀、private 双泪、protected 這些老朋友不用多做介紹,再來個 readonly密似,相當(dāng)于 final焙矛。
class Demo {
private a: string;
public b: string;
protected c: string;
readonly name: string; //相當(dāng)于Java里的final,在初始化或構(gòu)造函數(shù)里一定要被初始化残腌,至多賦值一次
}
3.抽象類
abstract class Animal {
abstract makeSound(): void;
move(): void {
console.log('roaming the earch...');
}
}
參考內(nèi)容
ES6:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference
TS手冊:https://www.tslang.cn/docs/handbook/basic-types.html
TS參考: https://zhuanlan.zhihu.com/p/98709371