国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

ES6新語(yǔ)法疑點(diǎn)簡(jiǎn)析

silencezwm / 2604人閱讀

摘要:本文涵蓋了一些新語(yǔ)法可能造成疑惑的地方和一些建議。新接口的迭代器參數(shù)的誤調(diào)用接口及集合類(lèi)構(gòu)造器的參數(shù),可以放入支持迭代器的內(nèi)容,而不局限于數(shù)組兼容。新集合類(lèi)容器的構(gòu)造器集合類(lèi)容器不可以通過(guò)非方式來(lái)構(gòu)造。

本文涵蓋了一些ES6新語(yǔ)法可能造成疑惑的地方和一些建議。

1# 箭頭函數(shù)

箭頭函數(shù)看起來(lái)像是匿名函數(shù)表達(dá)式function(){}的簡(jiǎn)寫(xiě),然而它不是。

這個(gè)例子應(yīng)該很容易看出來(lái)會(huì)有怎樣的問(wèn)題:

function Apple(){}

Apple.prototype.check = ()=>{
    console.log(this instanceof Apple);
};

(new Apple()).check() // false

使用apply、call、bind改變箭頭函數(shù)的this指向呢?

var i = 0;
var xx = ()=>{ console.log(++i, this) };
var yy = function(){ console.log(++i, this) };

xx();             // 1 window
xx.apply([]);     // 2 window
xx.bind([])();    // 3 window
yy();             // 4 window
yy.apply([]);     // 5 []
yy.bind([])();    // 6 []

顯然apply、call、bind無(wú)法改變箭頭函數(shù)的this指向,箭頭函數(shù)的this確定后無(wú)法更改。

在這些場(chǎng)景中不要使用箭頭函數(shù):

當(dāng)你需要正常使用this binding時(shí),如函數(shù)構(gòu)造器、prototype

當(dāng)你需要?jiǎng)討B(tài)改變this的時(shí)候

針對(duì)工作報(bào)酬和代碼量呈反比的程序猿,在需要用到this binding的場(chǎng)景里,可能比較適合的簡(jiǎn)寫(xiě)形式是在新對(duì)象字面量語(yǔ)法里提供的:

var obj = {
    hello() { // 少寫(xiě)了一個(gè)function耶!
        console.log("world")
    } 
};
2# Promise 2.1# then
//1
fetch(xx, oo).then(handleResultAndReturnsAnPromise(result));
//2 
fetch(xx, oo).then(handleResultAndReturnsAnPromise);
//3 
fetch(xx, oo).then((result) => handleResultAndReturnsAnPromise(result));
//4
fetch(xx, oo).then(function(result) { handleResultAndReturnsAnPromise(result) });

1與2、3、4均不等價(jià):1同步調(diào)用了handleResultAndReturnsAnPromise;而2~4均會(huì)導(dǎo)致handleResultAndReturnsAnPromise在fetch之后完成

2與3/4則是運(yùn)行時(shí)的調(diào)用棧有區(qū)別,3/4額外創(chuàng)建了一個(gè)匿名函數(shù)。

3與4除了this binding的區(qū)別,4的調(diào)用返回值沒(méi)有進(jìn)行返回,這樣將導(dǎo)致promise鏈斷裂。

1中需要注意的是,then(promise)里面?zhèn)饕粋€(gè) Promise 對(duì)象是沒(méi)有什么意義的,它會(huì)被當(dāng)成then(null),在下面推薦的文章中,它被稱(chēng)作“Promise 穿透”

更多的令人混淆的案例,請(qǐng)繼續(xù)閱讀《談?wù)勈褂?promise 時(shí)候的一些反模式》。

2.2# catch

在node的一些版本中,采用Promise并忘記給promise鏈增加catch(fn)then(null, fn),將導(dǎo)致代碼中的異常被吞掉。

這個(gè)問(wèn)題在新的v8中(node 6.6+,chrome最新版)會(huì)導(dǎo)致一個(gè)UnhandledPromiseRejectionWarning,防止開(kāi)發(fā)遺漏。

node -e "Promise.reject()"
# UnhandledPromiseRejectionWarning: Unhandled promise rejection
2.3# resolve

Promise接口和jQuery實(shí)現(xiàn)的接口不一樣,resolve只接受單參數(shù),then的回調(diào)也只能拿到單參數(shù)。

在Promise規(guī)范中的單參數(shù)鏈?zhǔn)秸{(diào)用場(chǎng)景下,可以利用解構(gòu)、_.spread、訪問(wèn)自由變量等方式來(lái)處理多個(gè)過(guò)程中得到的值:

new Promise(function(resolve, reject){
    let something = 1,
        otherstuff = 2;
    resolve({something, otherstuff});
}).then(function({something, otherstuff}){
    // handle something and otherstuff
});
Promise.all([
    Promise.resolve(40), Promise.resolve(36)
]).then(
    _.spread(function(first, second){
        // first: 40, second: 36
    })
);
let someMiddleResult;
fetch()
    .then(function(fetchResult){
        someMiddleResult = fetchResult;
    })
    .then(otherHandleFn)
    .then(function(otherHandleFnResult){
        // use both someMiddleResult and otherHandleFnResult now
    })
2.4# reject / throw

出現(xiàn)reject接口,應(yīng)該是第一次前端有機(jī)會(huì)拿異常處理流程做正常流程(比如*)。不要這樣做。

由于reject(new Error(""))throw new Error("")都能作為catch的入口,一些不可預(yù)知的錯(cuò)誤被拋出的時(shí)候,這樣的處理方式將會(huì)復(fù)雜化catch內(nèi)的代碼。不要用異常處理邏輯來(lái)做正常處理流程,這個(gè)規(guī)則保證了代碼可讀性與可維護(hù)性。

throwreject都可以作為catch的入口,它們更加詳細(xì)的區(qū)別如下:

new Promise((resolve, reject) => {
    setTimeout(function(){
        reject(new Error("hello"));
    });
}).catch(() => console.log("reject"));
// reject

new Promise((resolve, reject) => {
    setTimeout(function(){
        throw new Error("hello");
    });
}).catch(() => console.log("throw"));
// Uncaught Error: hello

reject能夠“穿透”回調(diào);而throw限于函數(shù)作用域,無(wú)法“穿透”回調(diào)。

建議:

正常流程請(qǐng)選擇在then的時(shí)候if..else,不要用reject替代

在需要走異常處理流程的時(shí)候封裝Error拋出,可以最大化的化簡(jiǎn)catch回調(diào)里面的處理邏輯,類(lèi)似于e instanceof MyDesignedError

由于回調(diào)函數(shù)里的throw無(wú)法被自動(dòng)捕獲到,如果需要在回調(diào)中reject當(dāng)前 promise,那么我們需要用reject而不是throw

在使用Promise接口的 polyfill 的場(chǎng)景,應(yīng)當(dāng)在reject后加一個(gè)return

3# let & const & var

看起來(lái)letconst的組合就像是一個(gè)能完全滅掉var的新特性,但對(duì)舊代碼不能簡(jiǎn)單的正則替換掉var,因?yàn)槲覀兲?xí)慣于濫用它的特性了——主要是聲明提升。

一些情形下會(huì)造成語(yǔ)法錯(cuò)誤:

try {
    let a = 10;

    if (a > 2) {
        throw new Error();
    }

    // ...
} catch (err) {
    console.log(a);
    // 若為var聲明,不報(bào)錯(cuò)
    // 若為const、let聲明:Uncaught ReferenceError: a is not defined
}

除了try..catch,隱式造就的塊級(jí)作用域在forif..else中也將造成問(wèn)題:

if(false) {
    let my = "bad";
} else {
    console.log(my); // ReferenceError: my is not defined
}

解決方案倒是很簡(jiǎn)單,將作用域內(nèi)的let放在更靠外層的位置即可。

varletconst的區(qū)別如下(部分參考自stackoverflow*):

作用域:letconst將創(chuàng)造一個(gè)塊級(jí)作用域,在作用域之外此變量不可見(jiàn),作用域外訪問(wèn)將導(dǎo)致SyntaxErrorvar遵循函數(shù)級(jí)作用域

全局影響:全局作用域下的var使用等同于設(shè)置window/global之上的內(nèi)容,但letconst不會(huì)

提升行為:var聲明有提升到當(dāng)前函數(shù)作用域頂部的特性,但constlet沒(méi)有,在聲明前訪問(wèn)變量將導(dǎo)致SyntaxError

重新賦值:對(duì)const變量所做的重新賦值將導(dǎo)致TypeError,而varlet不會(huì)

重新聲明:var聲明的變量使用var再次聲明不會(huì)出現(xiàn)SyntaxError,但constlet聲明的變量不能被重新聲明,也不能覆蓋掉之前任何形式的聲明:

var vVar = 1;
const vConst = 2;
let vLet = 3;

var vVar = 4;     // success
let vVar = 5;     // SyntaxError
const vVar = 6;   // SyntaxError

var vConst = 7;   // SyntaxError
let vConst = 8;   // SyntaxError
const vConst = 9; // SyntaxError

var vLet = 10;    // SyntaxError
let vLet = 11;    // SyntaxError
const vLet = 12;  // SyntaxError
4# 邊界

本篇章集結(jié) ES6 給予的不同邊界條件,部分編譯自 You don"t know JS

4.1# 函數(shù)默認(rèn)參數(shù)值
function before(a) { var a = a || 1; console.log(a); }
function after(a = 1) { console.log(a); }

before(NaN) // 1
after(NaN) // NaN

新的寫(xiě)法的fallback邏輯只針對(duì)undefined有效。

4.2# Object.assign

Object.assign將賦予所有的可枚舉值,但不包含從原型鏈繼承來(lái)的值:

let arr = [1, 2, 3],
    obj = {};
Object.assign(obj, arr);

obj[1] // 2
obj.length // undefined
Object.getOwnPropertyDescriptors(arr).length.enumerable // false

此外:Object.assign僅僅進(jìn)行淺拷貝:

var orig = {
    a: [1, 2, 3]
},
    nObj = {};

Object.assign(nObj, orig);
orig.a.push(4);
nObj.a // [1, 2, 3, 4]
4.3# NaN

Number.isNaN和全局空間中的isNaN的區(qū)別在于不存在隱式轉(zhuǎn)換:

isNaN("number") // true
Number.isNaN("number") // false

Object.is除了區(qū)分正負(fù)零這個(gè)非常小眾的邊界,這個(gè)接口相對(duì)===更大的意義是判斷NaN:

Object.is(NaN, NaN); // true
NaN === NaN; // false
Object.is(+0, -0); // false
+0 === -0; // true

同樣的,arr.includes(xx)arr.lastIndexOf(xx) > -1好的地方也包括對(duì)于NaN的處理:

[1, 2, NaN].includes(NaN); // true
4.4# Number

isFiniteNumber.isFinite的區(qū)別也是后者不存在隱式轉(zhuǎn)換:

isFinite("42");        // true
Number.isFinite("42"); // false

Number.isInteger表示一個(gè)數(shù)是不是小數(shù),和x === Math.floor(x)的區(qū)別在于對(duì)Infinity的處理

Number.isInteger(Infinity);        // false
Infinity === Math.floor(Infinity); // true

Number.isSafeInteger表示傳入的數(shù)值有沒(méi)有精度損失,它比較的是數(shù)字是否在Number.MIN_SAFE_INTEGERNumber.MAX_SAFE_INTEGER之間:

Number.isSafeInteger(Math.pow(2, 53) - 1); // true
Number.isSafeInteger(Math.pow(2, 53)); // false

我曾整理過(guò)Number的數(shù)軸(*),也寫(xiě)過(guò)JavaScript中的一些數(shù)字內(nèi)存模型的demo,其中有一部分值沒(méi)有直接的量來(lái)表示,但現(xiàn)在有了。

從負(fù)無(wú)窮往正無(wú)窮來(lái)看,是這樣的:

Number.NEGATIVE_INFINITY 負(fù)無(wú)窮

-Number.MAX_VALUE 能表示的最小數(shù)字,更小被視為負(fù)無(wú)窮,等于-(2^53-1)*(2^971)

Number.MIN_SAFE_INTEGER(新) 沒(méi)有精度誤差的最小數(shù),等于-(2^53-1)

0 正負(fù)零

Number.EPSILON(新) IEEE 754規(guī)范下的精度位允許的最小差異值,等于2^-52

Number.MIN_VALUE 能表示的最小正整數(shù),這是一個(gè)IEEE 754規(guī)范下的反規(guī)格化值,等于2^-1074

Number.MAX_SAFE_INTEGER(新) 沒(méi)有精度誤差的最大數(shù),,等于2^53-1

Number.MAX_VALUE 能表示的最大數(shù)字,更大被視為正無(wú)窮,等于(2^53-1)*(2^971)

Number.INFINITY 正無(wú)窮

比較令人混淆的是Number.EPSILONNumber.MIN_VALUE,前者為精度位允許的最小差異值,考慮的是浮點(diǎn)數(shù)的精度位;而后者考慮的是利用到浮點(diǎn)數(shù)的所有位置能夠表示的最小正數(shù)值。

5# 怪奇錯(cuò)誤展

本節(jié)收集了一些奇奇怪怪的錯(cuò)誤提示,正常寫(xiě)出的代碼不會(huì)導(dǎo)致它們,沒(méi)有興趣可以略過(guò)。

5.1# 新接口的迭代器參數(shù)
Array.from(1, 2, 3) // Array.of(1,2,3)的誤調(diào)用
// 2 is not a function

Array.fromPromise.all接口及集合類(lèi)構(gòu)造器的參數(shù),可以放入支持迭代器的內(nèi)容,而不局限于數(shù)組(node 0.12+兼容)。這里其實(shí)嘗試去調(diào)用了參數(shù)的迭代器Symbol.iterator

5.2# 新集合類(lèi)容器的構(gòu)造器
Array(); // []
Set(); // Uncaught TypeError: Constructor Set requires "new"

集合類(lèi)容器Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array Set不可以通過(guò)非new方式來(lái)構(gòu)造。

5.3# Tagged Template
var x = 30
`abcdefg`
// Uncaught TypeError: 30 is not a function

模版語(yǔ)法可能是ES6最為顯然的語(yǔ)法,但它的擴(kuò)展形式Tagged Template在極端場(chǎng)景可能造成一個(gè)奇怪的報(bào)錯(cuò),算是對(duì)不寫(xiě)分號(hào)黨造成的又一個(gè)暴擊*。

6# 欺負(fù)新來(lái)的

本篇章集結(jié)一些被濫用的特性。

6.1

解構(gòu)特性很棒,它可以在promise這樣的單參數(shù)鏈?zhǔn)秸{(diào)用場(chǎng)景或是正則匹配場(chǎng)景中大方光芒,更為經(jīng)典的是python風(fēng)格的[y, x] = [x, y]

但如果一個(gè)人鐵了心要瘋狂解構(gòu),新來(lái)維護(hù)這份代碼的人就要默默流下痛苦的眼淚了:

// 新人:是什么阻止了你用 a2 = [o1[a], o1[b], o1[c]] ……
var o1 = { a: 1, b: 2, c: 3 },
    a2 = [];

( { a: a2[0], b: a2[1], c: a2[2] } = o1 );
// 老人:看得爽嗎
var { a: { b: [ c, d ], e: { f } }, g } = obj;
// 主管:寫(xiě)到一半這個(gè)程序猿已經(jīng)被打死了
var x = 200, y = 300, z = 100;
var o1 = { x: { y: 42 }, z: { y: z } };

( { y: x = { y: y } } = o1 );
( { z: y = { y: z } } = o1 );
( { x: z = { y: x } } = o1 );

一個(gè)可以嘗試的保持代碼可讀性的方法,是盡量保證解構(gòu)的層次低。

6.2

新對(duì)象字面量也很不錯(cuò),新的rest操作符也很實(shí)用,但是如果你們把它們混在一起……下面進(jìn)一段代碼賞析(*):

export const sharePostStatus = createReducer( {}, {
    [ PUBLICIZE_SHARE ]: ( state, { siteId, postId } ) => ( { ...state, [ siteId ]: { ...state[ siteId ], [ postId ]: {
        requesting: true,
    } } } ),
    [ PUBLICIZE_SHARE_SUCCESS ]: ( state, { siteId, postId } ) => ( { ...state, [ siteId ]: { ...state[ siteId ], [ postId ]: {
        requesting: false,
        success: true,
    } } } ),
    [ PUBLICIZE_SHARE_FAILURE ]: ( state, { siteId, postId, error } ) => ( { ...state, [ siteId ]: { ...state[ siteId ], [ postId ]: {
        requesting: false,
        success: false,
        error,
    } } } ),
    [ PUBLICIZE_SHARE_DISMISS ]: ( state, { siteId, postId } ) => ( { ...state, [ siteId ]: {
        ...state[ siteId ], [ postId ]: undefined
    } } ),
} );

盡可能的保持代碼的可讀性,一行只用不超過(guò)2個(gè)ES6特性或許是一個(gè)可操作的方案。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/81332.html

相關(guān)文章

  • Loader學(xué)習(xí),簡(jiǎn)析babel-loader

    摘要:用來(lái)轉(zhuǎn)換內(nèi)容,內(nèi)部調(diào)用了方法進(jìn)行轉(zhuǎn)換,這里簡(jiǎn)單介紹一下的原理將代碼解析成,對(duì)進(jìn)行轉(zhuǎn)譯,得到新的,新的通過(guò)轉(zhuǎn)換成,核心方法在中的方法,有興趣可以去了解一下。將函數(shù)傳入?yún)?shù)和歸并,得到。通常我們是用不上的,估計(jì)在某些中可能會(huì)使用到。 什么是Loader? 繼上兩篇文章webpack工作原理介紹(上篇、下篇),我們了解到Loader:模塊轉(zhuǎn)換器,也就是將模塊的內(nèi)容按照需求裝換成新內(nèi)容,而且每...

    wpw 評(píng)論0 收藏0
  • Immer.js簡(jiǎn)析

    摘要:所以整個(gè)過(guò)程只涉及三個(gè)輸入狀態(tài),中間狀態(tài),輸出狀態(tài)關(guān)鍵是是如何生成,如何應(yīng)用修改,如何生成最終的。至此基本把上的模式解析完畢。結(jié)束實(shí)現(xiàn)還是相當(dāng)巧妙的,以后可以在狀態(tài)管理上使用一下。 開(kāi)始 在函數(shù)式編程中,Immutable這個(gè)特性是相當(dāng)重要的,但是在Javascript中很明顯是沒(méi)辦法從語(yǔ)言層面提供支持,但是還有其他庫(kù)(例如:Immutable.js)可以提供給開(kāi)發(fā)者用上這樣的特性,所...

    Aceyclee 評(píng)論0 收藏0
  • Immer.js簡(jiǎn)析

    摘要:所以整個(gè)過(guò)程只涉及三個(gè)輸入狀態(tài),中間狀態(tài),輸出狀態(tài)關(guān)鍵是是如何生成,如何應(yīng)用修改,如何生成最終的。至此基本把上的模式解析完畢。結(jié)束實(shí)現(xiàn)還是相當(dāng)巧妙的,以后可以在狀態(tài)管理上使用一下。 開(kāi)始 在函數(shù)式編程中,Immutable這個(gè)特性是相當(dāng)重要的,但是在Javascript中很明顯是沒(méi)辦法從語(yǔ)言層面提供支持,但是還有其他庫(kù)(例如:Immutable.js)可以提供給開(kāi)發(fā)者用上這樣的特性,所...

    dackel 評(píng)論0 收藏0
  • 前端計(jì)劃——JavaScript正則表達(dá)式快速入門(mén)

    摘要:前言正則表達(dá)式時(shí)處理字符串中常用的手法,本文以簡(jiǎn)單的方式,快速展示了中正則相關(guān)的基礎(chǔ)知識(shí)點(diǎn)。文末還提供了幾個(gè)簡(jiǎn)單的正則相關(guān)面試題。接下來(lái)是正則部分,注意后面的并不匹配,也就是比如,實(shí)際匹配的值是和,在和后面加上,就完成了預(yù)期。 前言:正則表達(dá)式時(shí)處理字符串中常用的手法,本文以簡(jiǎn)單的方式,快速展示了JavaScript中正則相關(guān)的基礎(chǔ)知識(shí)點(diǎn)。文末還提供了幾個(gè)簡(jiǎn)單的正則相關(guān)面試題。個(gè)人總結(jié)...

    Xufc 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<