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

資訊專欄INFORMATION COLUMN

JS數組中那些你知道或不知道的

jackzou / 3191人閱讀

摘要:當且僅當使用至少兩個參數調用構造函數時,此描述才適用。斷言的值為返回。還有是定義指定長度數組時會出現什么事呢在源碼中有個的方法。轉換為數字對象轉換為數字的規則如下表參數類型結果返回。不同的是,可以選擇自定義上下文環境。


作者:陳大魚頭

github: KRISACHAN

JS中的Array

ecma-262中的定義:

Array對象是一種特殊對象,它會對數組索引屬性鍵進行特殊處理。

每個Array對象都有一個不可配置的length屬性,其最大值是232 - 1

Array()

當且僅當不帶參數調用Array構造函數時,此描述才適用。

執行過程:

    定義 numberOfArgs 傳遞給此函數的調用的實參數量;

    斷言: numberOfArgs 為 0;

    如果 NewTargetundefined ,就設置 newTarget活動函數對象(active-function-object,正在運行的執行上下文的函數組件) ,并且讓 newTarget 成為 NewTarget

    原型 proto 怎么辦?通過原生方法GetPrototypeFromConstructor(newTarget, "%ArrayPrototype%")來構造;

    返回原生方法ArrayCreate(0, proto)

魚頭注:NewTarget是啥?NewTarget是原生Class FunctionCallbackInfo(函數調用的callback上下文的信息)內的一個不變量,用來定義構造調用時的返回值(new.target)。

Array(len)

當且僅當使用一個參數調用Array構造函數時,此描述才適用。

執行過程:

    定義 numberOfArgs 為傳遞給此函數的調用的實參數量;

    斷言: numberOfArgs 為1;

    如果 NewTargetundefined ,就設置 newTarget活動函數對象 ,并且讓 newTarget 成為 NewTarget

    原型 proto 怎么辦?通過原生方法GetPrototypeFromConstructor(newTarget, "%ArrayPrototype%")來構造;

    然后定義arrayArrayCreate(0, proto)

    如果 len 的類型不是個Number,則:

      定義 defineStatusCreateDataProperty(array, "0", len)

      斷言:defineStatus為真;

      intLen(初始化長度) 為1。

    或者:

      定義intLenToUint32(len)(原生方法,將len轉換成0到232-1之間的整數值)

      如果intLen不等于len,拋出RangeError異常。

    執行Set(array, "length", intLen, true)(原生方法,給對象的屬性賦值)

    返回array

Array(...items)

當且僅當使用至少兩個參數調用Array構造函數時,此描述才適用。

執行過程:

    定義 numberOfArgs 為傳遞給此函數的調用的實參數量;

    斷言: numberOfArgs 大于等于2;

    如果 NewTargetundefined ,就設置 newTarget活動函數對象 ,并且讓 newTarget 成為 NewTarget

    原型 proto 怎么辦?通過原生方法GetPrototypeFromConstructor(newTarget, "%ArrayPrototype%")來構造;

    然后定義arrayArrayCreate(numberOfArgs, proto)

    定義 k 為0;

    定義 items為 正序傳入參數的 零源(zero-origined) 列表;

    重復,當 k 小于 numberOfArgs

      定義 PkToSting(k)

      定義 itemKitem[k]

      定義 defineStatusCreateDataProperty(array, Pk, itemK);

      斷言:defineStatus為真;

      k 加1。

    斷言: arraylength 值為 numberOfArgs

    返回 array

empty

上面的三種情況以上便是構造Array()時不同情況的具體實現。但是我們從上面的斷言可以知道,構造結果有可能為真,有可能為假。還有是定義指定長度數組時會出現什么事呢?

V8源碼 3.28.71(node0.12.18)Array 有個CloneElementAt的方法。定義如下:

在指定索引處克隆元素時,如果克隆失敗,則返回一個空句柄(任何原因)。

從這句話我們可以知道,當我們構造一個指定長度的 Array 時,由于有長度,所以會開辟相應下標的空間,但是因為該下標并沒有元素,所以就會返回empty,任何原因構造數組元素失敗時,都會返回一個empty

示例如下:

var arr = new Array(10);
arr // [empty × 10]
以上總結

上面是 ECMA 上的定義以及 V8 源碼的容錯處理,其實簡單來說就是:

調用 Array(args) 時:

    用原生方法 GetPrototypeFromConstructor 生成原型 proto

    判斷 args 的類型;

    如果為 undefined,則直接返回創建數組的原生方法 ArrayCreate

    如果為 number,則用原生方法 Set 創建 args 長度的數組,并通過原生方法 CloneElementAt 來創建 argsempty 作為數組元素,如果args 大于 232 - 1 的話,會報錯;

    如果為其他類型,則把 args 變成數組元素,并用 原生方法 CreateDataProperty 創建參數,然后返回創建數組的原生方法 ArrayCreate

類型轉換

類型轉換是一個經常出現在一些網上常見面試題或者奇技淫巧中的內容。那么關于數組的類型轉換,又是怎樣的呢?

首先我們要知道,在 JS 中類型轉換只有三種情況,分別是:

轉換為布爾值

轉換為數字

轉換為字符串

轉換為原始類型

對象在轉換類型的時候,會執行原生方法ToPrimitive

其算法如下:

    如果已經是 原始類型,則返回當前值;

    如果需要轉 字符串 則先調用toSting方法,如果此時是 原始類型 則直接返回,否則再調用valueOf方法并返回結果;

    如果不是 字符串,則先調用valueOf方法,如果此時是 原始類型 則直接返回,否則再調用toString方法并返回結果;

    如果都沒有 原始類型 返回,則拋出 TypeError類型錯誤。

當然,我們可以通過重寫Symbol.toPrimitive來制定轉換規則,此方法在轉原始類型時調用優先級最高。

// 下面例子來自YCK的小冊
const data = {
  valueOf () {
    return 1;
        },
  toString () {
    return "1";
        },
  [Symbol.toPrimitive]() {
    return 2;
  }
};
data + 1 // 3
轉換為布爾值

對象轉換為布爾值的規則如下表:

參數類型 結果
Undefined 返回 false
Null 返回 false
Boolean 返回 當前參數。
Number 如果參數為+0-0NaN,則返回 false;其他情況則返回 true
String 如果參數為空字符串,則返回 false;否則返回 true
Symbol 返回 true
Object 返回 true
轉換為數字

對象轉換為數字的規則如下表:

參數類型 結果
Undefined 返回 NaN
Null Return +0.
Boolean 如果參數為 true,則返回 1false則返回 +0
Number 返回當前參數。
String 先調用 ToPrimitive,再調用 ToNumber,然后返回結果。
Symbol 拋出 TypeError錯誤。
Object 先調用 ToPrimitive,再調用 ToNumber,然后返回結果。
轉換為字符串

對象轉換為字符串的規則如下表:

參數類型 結果
Undefined 返回 "undefined"
Null 返回 "null"
Boolean 如果參數為 true ,則返回 "true";否則返回 "false"
Number 調用 NumberToString,然后返回結果。
String 返回 當前參數。
Symbol 拋出 TypeError錯誤。
Object 先調用 ToPrimitive,再調用 ToString,然后返回結果。
數組的類型轉換

所以通過上面的轉換規則,我們是否能夠輕松地看懂以下的隱式轉換呢?

[1,2,3] + {a: 1, b: 2} // "1,2,3[object Object]"
[1,2,3] + 1 // "1,2,31"
[1,2,3] + true // "1,2,3true"
[1,2,3] + undefined // "1,2,3undefined"
[1,2,3] + null // "1,2,3null"
[1,2,3] + "123" // "1,2,3123"
[1,2,3] + Symbol("biu") // "Uncaught TypeError"

所以各位是否理解上述隱式轉換的答案呢?

關于API使用的一些經驗與思考

JS數組自帶了很多的方法,在現代工程化數據驅動的理念下,這些方法都是非常重要的。

loops

forEachArray 方法中比較基本的一個,作用也很簡單,與for,就是遍歷,循環。不同的是,forEach可以選擇自定義上下文環境。例子如下:

var arr1 = [1, 2, 3];
var arr2 = [5, 6, 7];
arr1.forEach(function (e, i, a) {
  console.log(e, this); // this為arr2
}, arr2);

但是如果forEach的回調函數是用箭頭函數定義的,那么就無法改變它原本指向的上下文環境。例子如下:

var arr1 = [1, 2, 3];
var arr2 = [5, 6, 7];
arr1.forEach((e, i, a) => {
  console.log(e, this); // this為window對象
}, arr2);

所以如果我們要實現以下這個功能:


<ul>
    <li class="1">1li>
    <li class="2">2li>
    <li class="3">3li>
    <li class="4">4li>
    <li class="5">5li>
ul>
<script>
    "use strict";
    var ul = document.querySelector("ul");
    ul.onClick = event => {
        var cls = event.target.className;
        ul.querySelectorAll("li").forEach(el => {
            el.style.color = (cls === el.className ");"#FFF" : "#FF0");
        });
    };
script>

在ES6以前的環境中,如果直接用for循環,會出現只能獲取到最后一個元素的問題,但是用forEach則沒有這個問題。

reduce

Array ES5 API reducereduceRight,可以輕松實現并歸元素的功能,例子如下:

如果我們需要實現一個這樣的對象:

{
    a: 1,
    b: 2,
    c: 3
    ...
};

那么用reduce就會變得很簡單:

var newArr = "a,b,c,d,e,f".split(",").reduce((acc, cur, idx) => {
    let o = {};
    if (Object.prototype.toString.call(acc) !== "[object Object]") {
        o[cur] = idx;
    } else {
        let newO = {};
        newO[cur] = idx;
        o = {
            ...acc,
            ...newO,
        };
    };
    return o;
}, "a");
性能

上面演示了通過JS數組API實現的一些功能,所以與for循環比性能如何呢?

var arr = new Array(100);

arr.forEach(data => {
  console.log(data);
});

for (var i = 0; i < arr.length; ++i) {
  console.log(arr[i]);
};

所以哪個更耗時間呢?

在公布結果之前,其實網上一直流傳著for循環性能比forEach性能好,考慮性能少用forEach的言論,其實以前的瀏覽器也是這種情況。

詳情可以看知乎的這篇評論:www.zhihu.com/question/54…

性能對比如下:

以下代碼測試環境為:Chrome 55.0.2883 / Windows 7 0.0.0

所以在9012年的如今,結果又會是如何呢?

以下代碼測試環境為:Chrome 73.0.3683 / Windows 10 0.0.0

通過上面的對比,結果已經很明顯了,我們要知道,現代的瀏覽器性能優化已經做得比以前好很多了,再加上電子設備本身的硬件也越來越好,所以代碼塊的性能不是我們首要的考慮因素。

在跟同行溝通的過程中,經常會看到有人為了扣那么一個兩個表達式的性能而煩惱,其實是這是沒有任何必要,原因也如上,我們應該優化的是我們表達式是否清晰明了,是否適合后期維護或拓展。



如果你、喜歡探討技術,或者對本文有任何的意見或建議,你可以掃描下方二維碼,關注微信公眾號“魚頭的Web海洋”,隨時與魚頭互動。歡迎!衷心希望可以遇見你。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/7296.html

相關文章

  • JS數組那些知道或不知道

    摘要:從這句話我們可以知道,當我們構造一個指定長度的時,由于有長度,所以會開辟相應下標的空間,但是因為該下標并沒有元素,所以就會返回,任何原因構造數組元素失敗時,都會返回一個。 作者:陳大魚頭 github: KRISACHAN JS中的Array ecma-262中的定義:Array對象是一種特殊對象,它會對數組索引屬性鍵進行特殊處理。 每個Array對象都有一個不可配置的lengt...

    BenCHou 評論0 收藏0
  • JS 適配器模式

    摘要:另外,適配器模式和其它幾個模式可能容易讓人迷惑,這里說一下大概的區別適配器和橋接模式雖然類似,但橋接的出發點不同,橋接的目的是將接口部分和實現部分分離,從而對他們可以更為容易也相對獨立的加以改變。 1. 簡介 適配器模式(Adapter)是將一個類(對象)的接口(方法或屬性)轉化成客戶希望的另外一個接口(方法或屬性),適配器模式使得原本由于接口不兼容而不能一起工作的那些類(對象)可以一...

    Jeffrrey 評論0 收藏0
  • 哪些知道或不知道css,在這里或許都齊全

    摘要:簡單就意味著更快的開發速度,更小的維護成本,同時往往具有更好的體驗下面我介紹哪些或許你不知道小技巧。默認為,此時陰影與元素同樣大。如果沒有指定,則由瀏覽器決定通常是的值,不過目前取透明。首先,我們要明白這里的最小寬度值是什么意思。 暑假實習的時候帶我的師傅,告訴我要注重基礎,底層實現原理。才能在日新月異的技術行業站住腳跟,以不變應萬變,萬丈高樓平地起,所以我們應該不斷的去學習,去交流。...

    Jackwoo 評論0 收藏0
  • 哪些知道或不知道css,在這里或許都齊全

    摘要:簡單就意味著更快的開發速度,更小的維護成本,同時往往具有更好的體驗下面我介紹哪些或許你不知道小技巧。默認為,此時陰影與元素同樣大。如果沒有指定,則由瀏覽器決定通常是的值,不過目前取透明。首先,我們要明白這里的最小寬度值是什么意思。 暑假實習的時候帶我的師傅,告訴我要注重基礎,底層實現原理。才能在日新月異的技術行業站住腳跟,以不變應萬變,萬丈高樓平地起,所以我們應該不斷的去學習,去交流。...

    Bryan 評論0 收藏0
  • 哪些知道或不知道css,在這里或許都齊全

    摘要:簡單就意味著更快的開發速度,更小的維護成本,同時往往具有更好的體驗下面我介紹哪些或許你不知道小技巧。默認為,此時陰影與元素同樣大。如果沒有指定,則由瀏覽器決定通常是的值,不過目前取透明。首先,我們要明白這里的最小寬度值是什么意思。 暑假實習的時候帶我的師傅,告訴我要注重基礎,底層實現原理。才能在日新月異的技術行業站住腳跟,以不變應萬變,萬丈高樓平地起,所以我們應該不斷的去學習,去交流。...

    fai1017 評論0 收藏0

發表評論

0條評論

jackzou

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<