你可能從未使用過的11+個JavaScript特性

⚠重要

這篇文章中描述的大多數功能已被暫停使用(甚至不推薦使用)。 它們仍然在許多圖書中很常見,所以值得學習。javascript

1、逗號運算符

, 是用於分隔表達式並返回鏈中最後一個表達式的運算符。前端

let oo = (1, 2, 3)
console.log(oo) // 3
複製代碼

這裏有三個主要表達式 123。全部這些表達式均被求值,最後一個賦給 oo。java

咱們在 for 循環中看到這個:c++

for(let i = 0, ii = 1; i< 10; i++, ii--) { ... }
複製代碼

當咱們要編寫短的 lambda 函數時,這會派上用場:git

const lb = (a, b, arr) => (arr.push(a*b), a*b)
複製代碼

這裏有兩個語句,第一個將乘法結果推入數組arr,第二個將乘數a和b推入數組。 第二個結果就是返回給調用者的內容。github

對於三元運算符,它也頗有用,由於與短lambda語法相同,它僅接受表達式而不是語句。編程

2、in

in 是用於檢查對象中屬性是否存在的關鍵字。 咱們在 for..in 循環中使用了它,但沒有意識到,其實 in 也是一個關鍵字:)數組

若是對象上存在屬性,則 in 將返回 true ,不然將返回 false安全

const o = {
    prop: 1
}
console.log("prop" in o) // true
複製代碼

看,in 能夠獨立使用,而不是在 for..in 中。markdown

它將檢查 "prop" 是否可做爲 o 對象中的屬性使用。 它返回 true ,由於咱們在 o 中定義了 "prop" 屬性。

若是咱們檢查未定義的屬性:

const o = {
    prop: 1
}
console.log("prop1" in o) // false
複製代碼

它返回 false ,由於 "prop1"o 中未定義。

3、Array 構造函數

你知道咱們能夠不使用傳統方法定義數組嗎?

const arr = [1, 2, 3]
複製代碼

怎麼樣?

咱們也可使用 Array

const arr = new Array(1, 2, 3)
複製代碼

傳遞給 Array 構造函數的參數的排列將構成其索引的基礎。

1 是第一個參數,其索引爲 0; 2 是第二個參數,其索引爲 1; 3 是第三個參數,其索引爲 2。

arr[0] // 1
arr[1] // 2
arr[2] // 3
複製代碼

因此,

const arr = new Array(1, 2, 3)
複製代碼

const arr = [1, 2, 3]
複製代碼

表達的是一個意思。

但使用 new Array() 有一個問題,例如:

var a = new Array(10, 20);
a[0] // 返回 10
a.length // 返回 2
複製代碼

但:

var a = new Array(10);
a[0] // 返回 undefined
a.length // 返回 10
複製代碼

當你僅給 Array 構造函數一個整數(大於等於 0 的整數,不然將會報錯)時,纔會發生這種狀況。 這是爲何喃?

其實,新的 Array 構造函數正在從某些編程語言中提取思想,在這些語言中,你須要爲數組指定內存,這樣就不會出現 ArrayIndexOutOfBounds 異常。

int *a = (int *) malloc( 10*sizeof(int) ); // ya ol' c
int *a = new int[10]; // c++
int[] a = new int[10]; // java
複製代碼

是的,它其實是在建立一個長度爲 10 的數組。咱們在 Javascript 中沒有 sizeof 函數,可是 toString 足以證實這一點。

a.toString() // 返回 ",,,,,,,,," 它至關於 [,,,,,,,,,]
a // [empty × 10]
複製代碼

因此,當將一個參數傳遞給的 new Array,將致使 JS 引擎爲傳遞的參數大小的數組分配空間。

而且這也在 EcmaScript 規範中:

看,這不是矛盾的。 規格中都有全部描述。 在得出任何結論以前,咱們應該始終先閱讀任何語言的規範。

4、Function 構造函數

你是否知道咱們可使用 Function 構造函數定義 Function

你不明白吧? 讓我更清楚。 在 JavaScript 中,咱們定義以下函數:

const mul = (a, b) => a * b

// 或
function mul(a, b) {
    return a * b
}

// 或
const mul = function(a, b) {
    return a * b
}
複製代碼

咱們也能夠這樣作,來實現相同的功能:

const mul = new Function("a", "b", "return a * b")
複製代碼

傳遞給 Function 的參數造成函數的參數和主體。 變量 mul 成爲函數名稱。

而且,最後一個參數將是函數的主體,而最後一個參數以前的參數將成爲函數的參數。

在在 mul 中。 "a""b" 是函數將接收的參數,"return a * b" 是函數的主體。 它實現將 "a""b" 相乘並返回結果。

咱們使用 mul(…) 調用該函數,並傳入參數:

const mul = new Function("a", "b", "return a * b")

console.log(mul(7, 8)) // 56
複製代碼

根據 MDN:

Function 構造函數建立一個新的 Function 對象。直接調用此構造函數可用動態建立函數,但會遭遇來自 eval 的安全問題和相對較小的性能問題。然而,與 eval 不一樣的是,Function 構造函數只在全局做用域中運行。

5、數組解構

咱們能夠經過使用元素的索引號來分解數組中的元素。

const arr = [1, 2, 3]
複製代碼

元素 123 的索引分別爲 0、一、2,即:

arr[0] // 1
複製代碼

在平常開發中,咱們最常使用的是對象解構:

let o = {
    prop: 1
}
o["prop"] // 1

// 解構
const {prop} = o
prop // 1
複製代碼

因此,咱們將解構用於數組上:

const arr = [1, 2, 3]
const { 0: firstA, 1: secA, 2: thirdA  } = arr

firstA // 1
secA // 2
thirdA // 3
複製代碼

因此咱們可使用索引號來提取元素。索引是定義數組中元素位置的屬性。

const arr = [1, 2, 3]
複製代碼

至關於:

const arr = {
    0: 1,
    1: 2,
    2: 3,
    length: 3
}
複製代碼

數組也是對象,這就是爲何要對其進行對象分解的緣由,可是還有一種特殊的數組分解語法:

const [first, second, third] = arr

first // 1
second // 2
third // 3
複製代碼

注意:應儘量避免知道數組中的特定位置信息(開始、結束索引是什麼)。

6、使用 length 屬性減小數組內容

數組中的 length 屬性表示數組中元素的數目。

const arr = [1, 2, 3]
arr.length // 3
複製代碼

減少 length 屬性值,會使 JS 引擎將數組元素個數減小到與 length 屬性的值相等。

const arr = [1, 2, 3]
arr.length // 3
arr.length = 1
arr // [1]
複製代碼

arrlength 屬性值更改成 1,所以 arr 減小了元素個數,使其等於 length 屬性值。

若是增長 length 屬性,則 JS 引擎將添加元素(未定義的元素)以使數組中的元素數量達到 length 屬性的值。

const arr = [1, 2, 3]
arr.length // 3
arr.length = 1
arr // [1]

arr.length = 5
arr // [1, empty × 4]
複製代碼

arr 中的元素只有一個,而後咱們將長度增長到 5 ,所以又增長了 4 個元素長度,使元素數達到 5。

7、Arguments

咱們可使用 arguments 對象獲取傳遞給函數的參數,而無需在函數中明肯定義 arguments 變量:

function myFunc() {
    console.log(arguments[0]) // 34
    console.log(arguments[1]) // 89
}

myFunc(34,89)
複製代碼

arguments 對象是數組索引的。 也就是說,屬性是數字,所以能夠經過鍵引用進行訪問。

arguments 對象是從 Arguments 類實例化的,該類具備一些很酷的屬性。

arguments.callee.name 指當前正在調用的函數的名稱。

function myFunc() {
    console.log(arguments.callee.name) // myFunc
}

myFunc(34, 89)
複製代碼

arguments.callee.caller.name 是指調用當前執行函數的函數的名稱。

function myFunc() {
    console.log(arguments.callee.name) // myFunc
    console.log(arguments.callee.caller.name) // myFuncCallee
}

(function myFuncCallee() {
    myFunc(34, 89)
})()
複製代碼

這在可變參數功能中特別有用。

8、跳過 ()

你是否知道實例化對象時能夠跳過方括號 ()

例如:

class D {
    logger() {
        console.log("D")
    }
}

// 通常狀況下,咱們這麼作:
(new D()).logger(); // D

// 其實,咱們能夠跳過 ():
(new D).logger(); // D
// 而且它能夠正常運行
複製代碼

即便在內置類中,括號也是可選的:

(new Date).getDay();
(new Date).getMonth();
(new Date).getYear();
複製代碼

9、void

void 是 JS 中的關鍵字,用於評估語句並返回未定義。

例如:

class D {
   logger() {
        return 89
    }
}

const d = new D

console.log(void d.logger()) // undefined
複製代碼

logger 方法應該返回 89 ,可是 void 關鍵字將使其無效並返回 undefined

我曾經讀到過 undefined 以前可能會被賦予另外一個值,而這會僞造其語義。 所以,使用 void 運算符可確保你獲得一個真正的 undefined 。 也用於最小化目的。

10、經過 __proto__ 繼承

_proto_ 是從 JavaScript 中的對象繼承屬性的方法。 __proto__Object.prototype 的訪問器屬性,它公開訪問對象的 [[Prototype]]

__proto__ 將其 [[Prototype]] 中設置的對象的全部屬性設置爲目標對象。

讓咱們看一個例子:

const l = console.log
const obj = {
    method: function() {
        l("method in obj")
    }
}
const obj2 = {}
obj2.__proto__ = obj
obj2.method() // method in obj
複製代碼

咱們有兩個對象常量: objobj2obj 具備 method 屬性。 obj2 是一個空的對象常量,即它沒有屬性。

咱們訪問 obj2__proto__ 並將其設置爲 obj 。 這會將經過 Object.prototype 可訪問的 obj 的全部屬性複製到 obj2 。 這就是爲何咱們能夠在 obj2 上調用方法而不會在沒有定義的狀況下獲得錯誤的緣由。

obj2 繼承了 obj 的屬性,所以 method 方法屬性將在其屬性中可用。

原型可用於對象,例如對象常量、對象、數組、函數、日期、RegEx、數字、布爾值、字符串。

11、一元運算符 +

一元 + 運算符將其操做數轉換爲數字類型。

+"23" // 23
+{} // NaN
+null // 0
+undefined // NaN
+{ valueOf: () => 67 } // 67
+"nnamdi45" // NaN
複製代碼

當咱們但願將變量快速轉換爲 Number 時,這很是方便。

12、一元運算符 -

一元運算符 - 將其操做數轉換爲 Number 類型,而後取反。

該運算符將一元 + 運算符的結果取反。 首先,它將操做數轉換爲其 Number 值,而後取反該值。

-"23" // -23
複製代碼

此處發生的是,字符串 "23" 將轉換爲其數字類型,從而獲得 23 。而後,此正數將轉換爲其負數形式 -23

-{} // NaN
-null // -0
-undefined // NaN
-{ valueOf: () => 67 } // -67
-"nnamdi45" // NaN
複製代碼

若是轉換爲數值的結果爲 NaN ,則不會應用取反。

取負 +0 產生 -0 ,取負 -0 產生 +0

- +0 // -0
- -0 // 0
複製代碼

十3、指數運算符 **

該運算符用於指定數字的指數。

在數學中, 2^3^ 意味着將 2 乘以三次:

2 * 2 * 2
複製代碼

咱們可使用 ** 運算符在 JS 中進行相同的操做:

2 ** 3 // 8
9 ** 3 // 729
複製代碼

總結

本文翻譯自 11+ JavaScript Features You’ve Probably Never Used

想看往期更過系列文章,點擊前往 github 博客主頁

走在最後

  1. ❤️玩得開心,不斷學習,並始終保持編碼。👨💻

  2. 若有任何問題或更獨特的看法,歡迎評論或直接聯繫瓶子君(公衆號回覆 123 便可)!👀👇

  3. 👇歡迎關注:前端瓶子君,每日更新!👇

相關文章
相關標籤/搜索