[轉]ES7、ES8、ES9、ES10新特性大盤點

ES7、ES8、ES9、ES10新特性大盤點

本文轉自:https://mp.weixin.qq.com/s/8bov6788ivV0sHzmwrn5lw

以下文章來源于前端工匠 ,作者浪里行舟君

前端工匠

前端工匠

我是浪里行舟,Github博客4000+star作者,致力于打造一系列能夠幫助初中級工程師提高的優質文章。
(給前端大全加星標,提升前端技能)

作者: 前端工匠 公號 / 浪里行舟君

前言

從 ECMAScript 2016(ES7)開始,版本發布變得更加頻繁,每年發布一個新版本,好在每次版本的更新內容并不多,本文會細說這些新特性,盡可能和舊知識相關聯,幫你迅速上手這些特性。

ES7新特性

1.Array.prototype.includes()方法

在ES6中我們有String.prototype.includes()可以查詢給定字符串是否包含一個字符,而在 ES7 中,我們在數組中也可以用 Array.prototype.includes 方法來判斷一個數組是否包含一個指定的值,根據情況,如果包含則返回true,否則返回false。

const arr = [1, 3, 5, 2, '8', NaN, -0]
arr.includes(1) // true
arr.includes(1, 2) // false 該方法的第二個參數表示搜索的起始位置,默認為0
arr.includes('1') // false
arr.includes(NaN) // true
arr.includes(+0) // true

在ES7之前想判斷數組中是否包含一個元素,有如下兩種方法,但都不如includes來得直觀:

  • indexOf()

indexOf()方法返回在數組中可以找到一個給定元素的第一個索引,如果不存在,則返回-1。

if (arr.indexOf(el) !== -1) {// ...
}

不過這種方法有兩個缺點,一是不夠語義化,要先找到參數值的第一個出現位置,所以要去比較是否不等于-1,表達起來不夠直觀。二是,它內部使用嚴格相等運算符(===)進行判斷,這會導致對NaN的誤判。

[NaN].indexOf(NaN)// -1
  • find() 和 findIndex()

數組實例的find方法,用于找出第一個符合條件的數組成員。另外,這兩個方法都可以發現NaN,彌補了數組的indexOf方法的不足。

[1, 4, -5, 10].find((n) => n < 0) // -5
[1, 5, 10, 15].findIndex(function(value) {return value > 9;
}) // 2
[NaN].findIndex(y => Object.is(NaN, y)) // 0

Array.prototype.includes()的支持情況:

2.求冪運算符**

在ES7中引入了指數運算符,具有與Math.pow()等效的計算結果

console.log(2**10);// 輸出1024zhicc
console.log(Math.pow(2, 10)) // 輸出1024

求冪運算符的支持情況:

ES8新特性

1.Async/Await

我們都知道使用Promise能很好地解決回調地獄的問題,但如果處理流程比較復雜的話,那么整段代碼將充斥著then,語義化不明顯,代碼不能很好地表示執行流程,那有沒有比Promise更優雅的異步方式呢?

假如有這樣一個使用場景:需要先請求a鏈接,等返回信息之后,再請求b鏈接的另外一個資源。下面代碼展示的是使用fetch來實現這樣的需求,fetch被定義在window對象中,它返回的是一個Promise對象

fetch('https://blog.csdn.net/').then(response => {console.log(response)return fetch('https://juejin.im/')}).then(response => {console.log(response)}).catch(error => {console.log(error)})

雖然上述代碼可以實現這個需求,但語義化不明顯,代碼不能很好地表示執行流程。基于這個原因,ES8引入了async/await,這是JavaScript異步編程的一個重大改進,提供了在不阻塞主線程的情況下使用同步代碼實現異步訪問資源的能力,并且使得代碼邏輯更加清晰。

async function foo () {try {let response1 = await fetch('https://blog.csdn.net/')console.log(response1)let response2 = await fetch('https://juejin.im/')console.log(response2)} catch (err) {console.error(err)}
}
foo()

通過上面代碼,你會發現整個異步處理的邏輯都是使用同步代碼的方式來實現的,而且還支持try catch來捕獲異常,這感覺就在寫同步代碼,所以是非常符合人的線性思維的。需要強調的是,await 不可以脫離 async 單獨使用,await 后面一定是Promise 對象,如果不是會自動包裝成Promise對象。

根據MDN定義,async是一個通過異步執行并隱式返回Promise作為結果的函數

async function foo () {return '浪里行舟'
}
foo().then(val => {console.log(val) // 浪里行舟
})

上述代碼,我們可以看到調用async 聲明的foo 函數返回了一個Promise對象,等價于下面代碼:

async function foo () {return Promise.resolve('浪里行舟')
}
foo().then(val => {console.log(val) // 浪里行舟
})

Async/Await的支持情況:

2.Object.values(),Object.entries()

ES5 引入了Object.keys方法,返回一個數組,成員是參數對象自身的(不含繼承的)所有可遍歷(enumerable)屬性的鍵名。ES8引入了跟Object.keys配套的Object.values和Object.entries,作為遍歷一個對象的補充手段,供for…of循環使用。

Object.values方法返回一個數組,成員是參數對象自身的(不含繼承的)所有可遍歷(enumerable)屬性的鍵值。

const obj = { foo: 'bar', baz: 42 };
Object.values(obj) // ["bar", 42]
const obj = { 100: 'a', 2: 'b', 7: 'c' };
Object.values(obj) // ["b", "c", "a"]

需要注意的是,如果屬性名為數值的屬性,是按照數值大小,從小到大遍歷的,因此返回的順序是b、c、a。

Object.entries()方法返回一個數組,成員是參數對象自身的(不含繼承的)所有可遍歷(enumerable)屬性的鍵值對數組。這個特性我們后面介紹ES10的Object.fromEntries()還會再提到。

const obj = { foo: 'bar', baz: 42 };
Object.entries(obj) // [ ["foo", "bar"], ["baz", 42] ]
const obj = { 10: 'xxx', 1: 'yyy', 3: 'zzz' };
Object.entries(obj); // [['1', 'yyy'], ['3', 'zzz'], ['10': 'xxx']]

Object.values()與Object.entries()兼容性一致,下面以Object.values()為例:

3.String padding

在ES8中String 新增了兩個實例函數 String.prototype.padStart 和 String.prototype.padEnd,允許將空字符串或其他字符串添加到原始字符串的開頭或結尾。我們先看下使用語法:

String.padStart(targetLength,[padString])
  • targetLength(必填):當前字符串需要填充到的目標長度。如果這個數值小于當前字符串的長度,則返回當前字符串本身。

  • padString(可選):填充字符串。如果字符串太長,使填充后的字符串長度超過了目標長度,則只保留最左側的部分,其他部分會被截斷,此參數的缺省值為 " "。

'x'.padStart(4, 'ab') // 'abax'
'x'.padEnd(5, 'ab') // 'xabab'

有時候我們處理日期、金額的時候經常要格式化,這個特性就派上用場:

'12'.padStart(10, 'YYYY-MM-DD') // "YYYY-MM-12"
'09-12'.padStart(10, 'YYYY-MM-DD') // "YYYY-09-12"

String padding的支持情況:

4.Object.getOwnPropertyDescriptors()

ES5的Object.getOwnPropertyDescriptor()方法會返回某個對象屬性的描述對象(descriptor)。ES8 引入了Object.getOwnPropertyDescriptors()方法,返回指定對象所有自身屬性(非繼承屬性)的描述對象。

const obj = {name: '浪里行舟',get bar () {return 'abc'}
}
console.log(Object.getOwnPropertyDescriptors(obj))

得到如下結果:該方法的引入目的,主要是為了解決Object.assign()無法正確拷貝get屬性和set屬性的問題。我們來看個例子:

const source = {set foo (value) {console.log(value)},get bar () {return '浪里行舟'}
}
const target1 = {}
Object.assign(target1, source)
console.log(Object.getOwnPropertyDescriptor(target1, 'foo'))

返回如下結果:

上面代碼中,source對象的foo屬性的值是一個賦值函數,Object.assign方法將這個屬性拷貝給target1對象,結果該屬性的值變成了undefined。這是因為Object.assign方法總是拷貝一個屬性的值,而不會拷貝它背后的賦值方法或取值方法

這時Object.getOwnPropertyDescriptors()方法配合Object.defineProperties()方法,就可以實現正確拷貝。

const source = {set foo (value) {console.log(value)},get bar () {return '浪里行舟'}
}
const target2 = {}
Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source))
console.log(Object.getOwnPropertyDescriptor(target2, 'foo'))

返回如下結果:

Object.getOwnPropertyDescriptors()的支持情況:

ES9新特性

1.for await of

for of方法能夠遍歷具有Symbol.iterator接口的同步迭代器數據,但是不能遍歷異步迭代器。ES9新增的for await of可以用來遍歷具有Symbol.asyncIterator方法的數據結構,也就是異步迭代器,且會等待前一個成員的狀態改變后才會遍歷到下一個成員,相當于async函數內部的await。現在我們有三個異步任務,想要實現依次輸出結果,該如何實現呢?

// for of遍歷
function Gen (time) {return new Promise(function (resolve, reject) {setTimeout(function () {resolve(time)}, time)})
}
async function test () {let arr = [Gen(2000), Gen(100), Gen(3000)]for (let item of arr) {console.log(Date.now(), item.then(console.log))}
}
test()

得到如下結果:

上述代碼證實了for of方法不能遍歷異步迭代器,得到的結果并不是我們所期待的,于是for await of就粉墨登場啦!

function Gen (time) {return new Promise(function (resolve, reject) {setTimeout(function () {resolve(time)}, time)})
}
async function test () {let arr = [Gen(2000), Gen(100), Gen(3000)]for await (let item of arr) {console.log(Date.now(), item)}
}
test()
// 1575536194608 2000
// 1575536194608 100
// 1575536195608 3000

使用for await of遍歷時,會等待前一個Promise對象的狀態改變后,再遍歷到下一個成員。

異步迭代器的支持情況:

2.Object Rest Spread

ES6中添加的最意思的特性之一是spread操作符。你不僅可以用它替換cancat()和slice()方法,使數組的操作(復制、合并)更加簡單,還可以在數組必須以拆解的方式作為函數參數的情況下,spread操作符也很實用。

const arr1 = [10, 20, 30];
const copy = [...arr1]; // 復制
console.log(copy);    // [10, 20, 30]
const arr2 = [40, 50];
const merge = [...arr1, ...arr2]; // 合并
console.log(merge);    // [10, 20, 30, 40, 50]
console.log(Math.max(...arr));    // 30 拆解

ES9通過向對象文本添加擴展屬性進一步擴展了這種語法。他可以將一個對象的屬性拷貝到另一個對象上,參考以下情形:

const input = {a: 1,b: 2,c: 1
}
const output = {...input,c: 3
}
console.log(output) // {a: 1, b: 2, c: 3}

上面代碼可以把 input 對象的數據都添加到 output 對象中,需要注意的是,如果存在相同的屬性名,只有最后一個會生效

const input = {a: 1,b: 2
}
const output = {...input,c: 3
}
input.a='浪里行舟'
console.log(input,output) // {a: "浪里行舟", b: 2} {a: 1, b: 2, c: 3}

上面例子中,修改input對象中的值,output并沒有改變,說明擴展運算符拷貝一個對象(類似這樣obj2 = {…obj1}),實現只是一個對象的淺拷貝。值得注意的是,如果屬性的值是一個對象的話,該對象的引用會被拷貝:

const obj = {x: {y: 10}};
const copy1 = {...obj};    
const copy2 = {...obj}; 
obj.x.y='浪里行舟'
console.log(copy1,copy2) // x: {y: "浪里行舟"} x: {y: "浪里行舟"}
console.log(copy1.x === copy2.x);    // → true

copy1.x 和 copy2.x 指向同一個對象的引用,所以他們嚴格相等。

我們再來看下 Object rest 的示例:

const input = {a: 1,b: 2,c: 3
}
let { a, ...rest } = input
console.log(a, rest) // 1 {b: 2, c: 3}

當對象 key-value 不確定的時候,把必選的 key 賦值給變量,用一個變量收斂其他可選的 key 數據,這在之前是做不到的。注意,rest屬性必須始終出現在對象的末尾,否則將拋出錯誤。

Rest與Spread兼容性一致,下列以spread為例:

3.Promise.prototype.finally()

Promise.prototype.finally() 方法返回一個Promise,在promise執行結束時,無論結果是fulfilled或者是rejected,在執行then()和catch()后,都會執行finally指定的回調函數。

fetch('https://www.google.com').then((response) => {console.log(response.status);}).catch((error) => { console.log(error);}).finally(() => { document.querySelector('#spinner').style.display = 'none';});

無論操作是否成功,當您需要在操作完成后進行一些清理時,finally()方法就派上用場了。這為指定執行完promise后,無論結果是fulfilled還是rejected都需要執行的代碼提供了一種方式,避免同樣的語句需要在then()和catch()中各寫一次的情況

Promise.prototype.finally()的支持情況:

4.新的正則表達式特性

ES9為正則表達式添加了四個新特性,進一步提高了JavaScript的字符串處理能力。這些特點如下:

  • s (dotAll) 標志

  • 命名捕獲組

  • Lookbehind 后行斷言

  • Unicode屬性轉義

(1)s(dotAll)flag

正則表達式中,點(.)是一個特殊字符,代表任意的單個字符,但是有兩個例外。一個是四個字節的 UTF-16 字符,這個可以用u修飾符解決;另一個是行終止符,如換行符(\n)或回車符(\r),這個可以通過ES9的s(dotAll)flag,在原正則表達式基礎上添加s表示:

console.log(/foo.bar/.test('foo\nbar')) // false
console.log(/foo.bar/s.test('foo\nbar')) // true

那如何判斷當前正則是否使用了 dotAll 模式呢?

const re = /foo.bar/s // Or, `const re = new RegExp('foo.bar', 's');`.
console.log(re.test('foo\nbar')) // true
console.log(re.dotAll) // true
console.log(re.flags) // 's'

(2)命名捕獲組

在一些正則表達式模式中,使用數字進行匹配可能會令人混淆。例如,使用正則表達式/(\d{4})-(\d{2})-(\d{2})/來匹配日期。因為美式英語中的日期表示法和英式英語中的日期表示法不同,所以很難區分哪一組表示日期,哪一組表示月份:

const re = /(\d{4})-(\d{2})-(\d{2})/;
const match= re.exec('2019-01-01');
console.log(match[0]);    // → 2019-01-01
console.log(match[1]);    // → 2019
console.log(match[2]);    // → 01
console.log(match[3]);    // → 01

ES9引入了命名捕獲組,允許為每一個組匹配指定一個名字,既便于閱讀代碼,又便于引用。

const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const match = re.exec('2019-01-01');
console.log(match.groups);          // → {year: "2019", month: "01", day: "01"}
console.log(match.groups.year);     // → 2019
console.log(match.groups.month);    // → 01
console.log(match.groups.day);      // → 01

上面代碼中,“命名捕獲組”在圓括號內部,模式的頭部添加“問號 + 尖括號 + 組名”(?),然后就可以在exec方法返回結果的groups屬性上引用該組名。

命名捕獲組也可以使用在replace()方法中,例如將日期轉換為美國的 MM-DD-YYYY 格式:

const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
const usDate = '2018-04-30'.replace(re, '$<month>-$<day>-$<year>')
console.log(usDate) // 04-30-2018

(3)Lookbehind 后行斷言

JavaScript 語言的正則表達式,只支持先行斷言,不支持后行斷言,先行斷言我們可以簡單理解為"先遇到一個條件,再判斷后面是否滿足",如下面例子:

let test = 'hello world'
console.log(test.match(/hello(?=\sworld)/))
// ["hello", index: 0, input: "hello world", groups: undefined]

但有時我們想判斷前面是 world 的 hello,這個代碼是實現不了的。在 ES9 就支持這個后行斷言了:

let test = 'world hello'
console.log(test.match(/(?<=world\s)hello/))
// ["hello", index: 6, input: "world hello", groups: undefined]

(?<…)是后行斷言的符號,(?..)是先行斷言的符號,然后結合 =(等于)、!(不等)、\1(捕獲匹配)。

(4)Unicode屬性轉義

ES2018 引入了一種新的類的寫法\p{…}和\P{…},允許正則表達式匹配符合 Unicode 某種屬性的所有字符。比如你可以使用\p{Number}來匹配所有的Unicode數字,例如,假設你想匹配的Unicode字符?字符串:

const str = '?';
console.log(/\d/u.test(str));    // → false
console.log(/\p{Number}/u.test(str));     // → true

同樣的,你可以使用\p{Alphabetic}來匹配所有的Unicode單詞字符:

const str = '?';
console.log(/\p{Alphabetic}/u.test(str));     // → true
// the \w shorthand cannot match ?
console.log(/\w/u.test(str));    // → false

同樣有一個負向的Unicode屬性轉義模板 \P{…}

console.log(/\P{Number}/u.test('?'));    // → false
console.log(/\P{Number}/u.test('?'));    // → true
console.log(/\P{Alphabetic}/u.test('?'));    // → true
console.log(/\P{Alphabetic}/u.test('?'));    // → false

除了字母和數字之外,Unicode屬性轉義中還可以使用其他一些屬性。

以上這幾個特性的支持情況:

ES10新特性

1.Array.prototype.flat()

多維數組是一種常見的數據格式,特別是在進行數據檢索的時候。將多維數組打平是個常見的需求。通常我們能夠實現,但是不夠優雅。

flat() 方法會按照一個可指定的深度遞歸遍歷數組,并將所有元素與遍歷到的子數組中的元素合并為一個新數組返回。

newArray = arr.flat(depth) 
// depth是指定要提取嵌套數組的結構深度,默認值為 1	

接下來我們看兩個例子:

const numbers1 = [1, 2, [3, 4, [5, 6]]]
console.log(numbers1.flat())// [1, 2, 3, 4, [5, 6]]
const numbers2 = [1, 2, [3, 4, [5, 6]]]
console.log(numbers2.flat(2))// [1, 2, 3, 4, 5, 6]

上面兩個例子說明flat 的參數沒有設置,取默認值 1,也就是說只扁平化第一級;當 flat 的參數大于等于 2,返回值就是 [1, 2, 3, 4, 5, 6] 了。

Array.prototype.flat的支持情況:

2.Array.prototype.flatMap()

有了flat方法,那自然而然就有Array.prototype.flatMap方法,flatMap() 方法首先使用映射函數映射每個元素,然后將結果壓縮成一個新數組。從方法的名字上也可以看出來它包含兩部分功能一個是 map,一個是 flat(深度為1)。

let arr = [1, 2, 3]
console.log(arr.map(item => [item * 2]).flat()) // [2, 4, 6]
console.log(arr.flatMap(item => [item * 2])) // [2, 4, 6]

實際上flatMap是綜合了map和flat的操作,所以它也只能打平一層

Array.prototype.flatmap的支持情況:

3.Object.fromEntries()

Object.fromEntries 這個新的API實現了與 Object.entries 相反的操作。這使得根據對象的 entries 很容易得到 object。

const object = { x: 23, y:24 };
const entries = Object.entries(object); // [['x', 23], ['y', 24]]
const result = Object.fromEntries(entries); // { x: 23, y: 24 }

ES2017引入了Object.entries, 這個方法可以將對象轉換為數組,這樣對象就可以使用數組原型中的眾多內置方法,比如map, filter、reduce,舉個例子,我們想提取下列對象obj中所有value大于21的鍵值對,如何操作呢?

// ES10之前
const obj = {a: 21,b: 22,c: 23
}
console.log(Object.entries(obj)) // [['a',21],["b", 22],["c", 23]]
let arr = Object.entries(obj).filter(([a, b]) => b > 21) // [["b", 22],["c", 23]]
let obj1 = {}
for (let [name, age] of arr) {obj1[name] = age
}
console.log(obj1) // {b: 22, c: 23}

上例中得到了數組arr,想再次轉化為對象,就需要手動寫一些代碼來處理,但是有了Object.fromEntries()就很容易實現

// 用Object.fromEntries()來實現
const obj = {a: 21,b: 22,c: 23
}
let res = Object.fromEntries(Object.entries(obj).filter(([a, b]) => b > 21))
console.log(111, res) // {b: 22, c: 23}

Object.fromEntries()的支持情況:

4.String.trimStart 和 String.trimEnd

移除開頭和結尾的空格,之前我們用正則表達式來實現,現在ES10新增了兩個新特性,讓這變得更簡單!

trimStart() 方法從字符串的開頭刪除空格,trimLeft()是此方法的別名。

let str = ' 前端工匠 '
console.log(str.length) // 6
str = str.trimStart()
console.log(str.length) // 5
let str1 = str.trim() // 清除前后的空格
console.log(str1.length) // 4
str.replace(/^\s+/g, '') // 也可以用正則實現開頭刪除空格

trimEnd() 方法從一個字符串的右端移除空白字符,trimRight 是 trimEnd 的別名。

let str = ' 浪里行舟 '
console.log(str.length) // 6
str = str.trimEnd()
console.log(str.length) // 5
let str1 = str.trim() //清除前后的空格
console.log(str1.length) // 4
str.replace(/\s+$/g, '') // 也可以用正則實現右端移除空白字符

String.trimStart和String.trimEnd 兩者兼容性一致,下圖以trimStart為例:

5.String.prototype.matchAll

如果一個正則表達式在字符串里面有多個匹配,現在一般使用g修飾符或y修飾符,在循環里面逐一取出。

function collectGroup1 (regExp, str) {const matches = []while (true) {const match = regExp.exec(str)if (match === null) breakmatches.push(match[1])}return matches
}
console.log(collectGroup1(/"([^"]*)"/g, `"foo" and "bar" and "baz"`))
// [ 'foo', 'bar', 'baz' ]

值得注意的是,如果沒有修飾符 /g, .exec() 只返回第一個匹配。現在通過ES9的String.prototype.matchAll方法,可以一次性取出所有匹配。

function collectGroup1 (regExp, str) {let results = []for (const match of str.matchAll(regExp)) {results.push(match[1])}return results
}
console.log(collectGroup1(/"([^"]*)"/g, `"foo" and "bar" and "baz"`))
// ["foo", "bar", "baz"]

上面代碼中,由于string.matchAll(regex)返回的是遍歷器,所以可以用for…of循環取出。

String.prototype.matchAll的支持情況:

6.try…catch

在ES10中,try-catch語句中的參數變為了一個可選項。以前我們寫catch語句時,必須傳遞一個異常參數。這就意味著,即便我們在catch里面根本不需要用到這個異常參數也必須將其傳遞進去

// ES10之前
try {// tryCode
} catch (err) {// catchCode
}

這里 err 是必須的參數,在 ES10 可以省略這個參數:

// ES10
try {console.log('Foobar')
} catch {console.error('Bar')
}

try…catch的支持情況:

7.BigInt

JavaScript 所有數字都保存成 64 位浮點數,這給數值的表示帶來了兩大限制。一是數值的精度只能到 53 個二進制位(相當于 16 個十進制位),大于這個范圍的整數,JavaScript 是無法精確表示的,這使得 JavaScript 不適合進行科學和金融方面的精確計算。二是大于或等于2的1024次方的數值,JavaScript 無法表示,會返回Infinity。

// 超過 53 個二進制位的數值,無法保持精度
Math.pow(2, 53) === Math.pow(2, 53) + 1 // true
// 超過 2 的 1024 次方的數值,無法表示
Math.pow(2, 1024) // Infinity

現在ES10引入了一種新的數據類型 BigInt(大整數),來解決這個問題。BigInt 只用來表示整數,沒有位數的限制,任何位數的整數都可以精確表示。

創建 BigInt 類型的值也非常簡單,只需要在數字后面加上 n 即可。例如,123 變為 123n。也可以使用全局方法 BigInt(value) 轉化,入參 value 為數字或數字字符串。

const aNumber = 111;
const aBigInt = BigInt(aNumber);
aBigInt === 111n // true
typeof aBigInt === 'bigint' // true
typeof 111 // "number"
typeof 111n // "bigint"

如果算上 BigInt,JavaScript 中原始類型就從 6 個變為了 7 個。

  • Boolean

  • Null

  • Undefined

  • Number

  • String

  • Symbol (new in ECMAScript 2015)

  • BigInt (new in ECMAScript 2019)

BigInt的支持情況:

8.Symbol.prototype.description

我們知道,Symbol 的描述只被存儲在內部的 [[Description]],沒有直接對外暴露,我們只有調用 Symbol 的 toString() 時才可以讀取這個屬性:

Symbol('desc').description;  // "desc"
Symbol('').description;      // ""
Symbol().description;        // undefined

Symbol.prototype.description的支持情況:

9.Function.prototype.toString()

ES2019中,Function.toString()發生了變化。之前執行這個方法時,得到的字符串是去空白符號的。而現在,得到的字符串呈現出原本源碼的樣子:

function sum(a, b) {return a + b;
}
console.log(sum.toString());
// function sum(a, b) {
//  return a + b;
// }

Function.prototype.toString()的支持情況:

參考資料

  • 再學JavaScript ES(6-10)全版本語法大全

  • ECMAScript 6 入門

  • MDN文檔

  • ES2019新特性你知道哪些?

  • ES2018新特性——每個JS開發者都需要了解

  • 細解JavaScript ES7 ES8 ES9 新特性

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/285102.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/285102.shtml
英文地址,請注明出處:http://en.pswp.cn/news/285102.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

熱榜!!!數據結構與算法:C語言版---數組與稀疏矩陣---強勢來襲!

數組是各種計算機語言中經常使用到的重要數據結構&#xff0c;一般的說&#xff1a;在內存中申請一片連續地址的存儲空間、存儲這些數、就稱為數組。 在C語言中&#xff0c;申請連續的存儲空間是很容易的事情&#xff0c;但難在多維數組的組織、以及數組數據的壓縮上&#xff…

C語言試題167之字符串加密和解密算法

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款刷算法、筆試、面經、拿大公司offer神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目:在本實例…

第一聲問候

前一篇《Emacs 是一臺計算機》理解了 Emacs 身為計算機的本質之后&#xff0c;在 Emacs 里編程就順理成章了。不過&#xff0c;在此之前&#xff0c;還需要略微介紹一下 Emacs 最基本的操作。 系統的不一致&#xff0c;令人有點煩躁 現在&#xff0c;也可以坦然地說&#xff0c…

破解支付寶AR紅包

支付寶新出的AR紅包沒多久&#xff0c;就有人破解了&#xff0c;大致原理是將上面的像素條遮擋下面的黑條&#xff0c;基本上得到模糊的圖就可以掃到紅包。不過現在大多是ps解決&#xff0c;那得有多麻煩啊&#xff0c;所以我用java寫了一個&#xff0c;效果還不錯。 先截屏&am…

在 Windows 上搭建配置 Jenkins 然后編譯打包 VS 項目

在 Windows 上搭建配置 Jenkins 然后編譯打包 VS 項目獨立觀察員 2022 年 7 月 6 日一、安裝1、下載并安裝 JRE &#xff08;Java 運行環境&#xff09;。2、下載 Windows 版本的 Jenkins 安裝包并安裝。3、安裝 Visual Studio&#xff0c;以供編譯項目使用。4、安裝 Advanced …

【ArcGIS微課1000例】0007:基于數字高程模型DEM生成剖面線、剖面圖

文章目錄 效果預覽數據分析工具介紹生成過程剖面圖編輯保存、導出剖面圖實驗數據下載效果預覽 數據分析 本實例使用到的原始數據為案例提供的規則格網DEM

[轉]javaandroid線程池

java多線程-概念&創建啟動&中斷&守護線程&優先級&線程狀態&#xff08;多線程編程之一&#xff09;java多線程同步以及線程間通信詳解&消費者生產者模式&死鎖&Thread.join()&#xff08;多線程編程之二&#xff09;java&android線程池-Exe…

C#實現清理系統內存

金山內存整理工具、360內存清理工具非常好用&#xff0c;可以將系統內存最小化&#xff0c;提升系統運行速度。其實這些事情C#也可以做到&#xff0c;原理就是對系統進程中的進程內存進行逐個優化。 網上大多推薦使用系統的SetProcessWorkingSetSize的函數API&#xff0c;但是經…

C語言試題168之獲取矩陣的最大值及其下標

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款刷算法、筆試、面經、拿大公司offer神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目:要求使用…

.Net下極限生產力之efcore分表分庫全自動化遷移CodeFirst

開始本次我們的主題就是極限生產力,其他語言望塵莫及的分表分庫全自動化Migrations Code-First 加 efcore 分表分庫無感開發還記得上次發布博客還是在上次,上次發布了如何兼容WTM框架后也有不少小伙伴來問我如何兼容如何遷移等問題,經過這么多框架的兼容我自己也認識到了一些問…

Hadoop日常管理與維護

本文描述了hadoop、hbase的啟動關閉、表操作以及權限管理。一、Hadoop服務的啟動與關閉1、啟動使用hadoop以及hbase自帶的腳本進行啟動&#xff0c;先啟動hadoop個服務&#xff0c;再啟動hbase服務。 hadoopbdi:~$ start-dfs.sh hadoopbdi:~$ start-yarn.sh hadoopbdi:~$ start…

Mathematica修改默認字體

1. 打開Option Inspector 2. 第一個下拉框選擇Global Preference, 搜索stylehints 3. 修改字體為想要換的字體FamilyName, 比如換成蘋果黑體 SimHei, 字體FamilyName自行研究 4. 效果 轉載于:https://www.cnblogs.com/dabaopku/p/6221960.html

基于JavaScript 數組的經典程序應用源碼(強烈建議收藏)

文章目錄設計一個數組輸入并顯示的程序。數組輸入和顯示選擇排序選擇排序排序程序包排序網頁楊輝三角形楊輝三角形網頁C語言畫一個sin(x)的曲線螺旋線訪問二維數組JavaScript數組的定義、使用都是非常簡單的&#xff0c;僅僅定義的話&#xff0c;就使用&#xff1a; var anew …

C語言試題169之誰家孩子跑得最慢

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款刷算法、筆試、面經、拿大公司offer神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目:張、王、…

【ArcGIS微課1000例】0008:ArcGIS中如何設置相對路徑?(解決圖層前紅色的感嘆號)

文章目錄 問題舉例問題分析解決辦法問題舉例 我們在使用ArcGIS時經常會碰到這樣的問題:將地圖文檔(.mxd)保存到本地并拷貝到別的電腦上或改變一個路徑時,出現數據丟失的現象,具體表現為圖層前面出現一個紅色的感嘆號,如下圖所示。 出現以上問題的根本原因是數據GSS.tif的…

IPC-----消息隊列

消息隊列&#xff08;報文隊列&#xff09;:兩個進程間通過發送數據塊的形式進行通信。一個進程把需要發送的消息通過一個函數發送到消息隊列中&#xff0c;另一個進程再從消息隊列中讀取該消息。函數&#xff1a;# include <sys/types.h># include <sys/ipc.h>key…

[轉]OKR結合CFR的管理模式

讀前預 無論任何管理書籍&#xff0c;都是圍繞著人性&#xff0c;如果激發員工的人性中的自尊和自我價值觀、自我成就感。 作為一名領導者&#xff0c;在管理前&#xff0c;必須要是冷靜&#xff0c;安靜的對待他人 約翰杜爾為谷歌送上大禮 “好主意”再加上”卓越的執行”&…

NetCore 國際化最佳實踐

NetCore 國際化最佳實踐ASP.NET Core中提供了一些本地化服務和中間件&#xff0c;可將網站本地化為不同的語言文化。ASP.NET Core中我們可以使用Microsoft.AspNetCore.Localization庫來實現本地化。但是默認只支持使用資源文件方式做多語言存儲&#xff0c;很難在實際場景中使用…

復分析——第1章——復分析準備知識(E.M. Stein R. Shakarchi)

第一章 復分析準備知識 (Preliminaries to Complex Analysis) The sweeping development of mathematics during the last two centuries is due in large part to the introduction of complex numbers; paradoxically, this is based on the seemingly absurd no…

網構軟件-Internetware

網構軟件&#xff0c;973項目提的一個概念。概念。作為一種新型軟件形態&#xff0c;它應該涵蓋哪些研究范疇&#xff1f;評價它成功的基本標準是什么&#xff1f;我們看待一件事物&#xff0c;首先都會從已知的認知空間里尋找與之對應者。那么&#xff0c;能與網構相對應的大概…