算法以前

這是我參與8月更文挑戰的第3天,活動詳情查看:8月更文挑戰javascript

image.png

數據結構與算法的關係

  • 數據結構:計算機存儲,組織數據的方式,就像鍋碗瓢盆。
  • 算法:一系列解決問題的清晰指令,就像食譜。
  • 程序 = 數據結構 + 算法
  • 數據結構爲算法提供服務,算法圍繞數據結構操做。

數據結構分類

  • 有序:棧,隊列,鏈表
  • 無序:集合,字典
  • 節點關聯性:樹,堆,圖

時間 / 空間複雜度

image.png

數學知識

log2

在數學中,對數是對求冪的逆運算,正如除法是乘法的逆運算,反之亦然。 [6] 這意味着一個數字的對數是必須產生另外一個固定數字(基數)的指數。 在簡單的狀況下,乘數中的對數計數因子。更通常來講,乘冪容許將任何正實數提升到任何實際功率,老是產生正的結果,所以能夠對於b不等於1的任何兩個正實數b和x計算對數。若是a的x次方等於N(a>0,且a≠1),那麼數x叫作以a爲底N的對數(logarithm),記做x=loga N。其中,a叫作對數的底數,N叫作真數。 [1]前端

矩陣

在數學中,矩陣(Matrix)是一個按照長方陣列排列的複數或實數集合 [1] ,最先來自於方程組的係數及常數所構成的方陣。這一律念由19世紀英國數學家凱利首先提出。java

對應在前端領域,是咱們的多維數組,和雙重for循環node

時間複雜度

在計算機科學中,時間複雜性,又稱時間複雜度,算法的時間複雜度是一個函數,它定性描述該算法的運行時間。這是一個表明算法輸入值的字符串的長度的函數。時間複雜度經常使用大O符號表述,不包括這個函數的低階項和首項係數。使用這種方式時,時間複雜度可被稱爲是漸近的,亦即考察輸入值大小趨近無窮時的狀況。web

一個算法花費的時間與算法中語句的執行次數成正比例,哪一個算法中語句執行次數多,它花費時間就多。一個算法中的語句執行次數稱爲語句頻度或時間頻度。記爲T(n)。正則表達式

function traverse(arr) {
    var n = arr.length;   		// 執行1次
    for(var i=0;i<n;i++) {		// var i = 0; 執行1次 | i < n 執行n次 | i++ 執行 n+1次
        console.log(arr[i])		// 執行n次
    }
}
複製代碼

執行次數:1 + 1 + n + (n + 1) + n = 3n + 3算法

通常狀況下,算法中基本操做重複執行的次數是問題規模n的某個函數,用T(n)表示,如有某個輔助函數f(n),使得當n趨近於無窮大時,T(n)/f (n)的極限值爲不等於零的常數,則稱f(n)是T(n)的同數量級函數。記做T(n)=O(f(n)),稱O(f(n)) 爲算法的漸進時間複雜度,簡稱時間複雜度。編程

時間複雜度計算:基於n趨向於無限大,3n + 3在n趨向於無限大的時候,3n + 3趨向於n。因此這裏的時間複雜度爲O(n)。數組

空間複雜度

空間複雜度(Space Complexity)是對一個算法在運行過程當中臨時佔用存儲空間大小的量度,記作S(n)=O(f(n))。好比直接插入排序的時間複雜度是O(n^2),空間複雜度是O(1) 。而通常的遞歸算法就要有O(n)的空間複雜度了,由於每次遞歸都要存儲返回信息。一個算法的優劣主要從算法的執行時間和所須要佔用的存儲空間兩個方面衡量。markdown

一個算法的空間複雜度只考慮在運行過程當中爲局部變量分配的存儲空間的大小,它包括爲參數表中形參變量分配的存儲空間和爲在函數體中定義的局部變量分配的存儲空間兩個部分。

function traverse(arr) {
    var n = arr.length;   		// n佔用1空間
    for(var i=0;i<n;i++) {		// arr佔用n空間
        console.log(arr[i])		// i佔用1空間
    }
}
複製代碼

空間複雜度爲O(n)。

數據結構簡介

數組

js原生支持的數據結構

const array = [1, 2, 3, 4, 5];
複製代碼

隊列

棧是一種先進先出(FIFO,First In First Out)的數據結構。 先進先出,js數組支持,限定使用方法:頭部彈出元素【shift】,尾部新增元素【push】

const array = [1, 2, 3, 4, 5];

array.push(6)
array.shift();

console.log(array);  // [2, 3, 4, 5, 6]
複製代碼

棧是一種後進先出(LIFO,Last In First Out)的數據結構。 後進先出,js數組支持,限定使用方法:尾部彈出元素【pop】,尾部新增元素【push】

const array = [1, 2, 3, 4, 5];

array.push(6);
array.pop()

console.log(array);   // [1, 2, 3, 4, 5]
複製代碼

鏈表

多個元素組成的列表 元素存儲不連續,經過next指針鏈接一塊兒。

var node1Item =  {
	value: 'value',
  next: node2Item
};
  
var node2Item =  {
	value: 'value',
  next: null
}
複製代碼

數組 VS 鏈表

image.png

集合

一組無序且惟一的數據結構。 ES6 集合:Set。 集合的經常使用操做:去重,判斷某元素是否在集合中,求交集。

const array = [1, 2, 3, 4, 5];

// 去重
const set1 = [...new Set(array)];

// 判斷元素是否在集合中
const set2 = new Set(array);
set2.has(2);

// 求取交集
const set3 = new Set(array);
const set4 = new Set([2, 4, 6]);

const joinSet = new Set([...set3].filter(item => set4.has(item)))
複製代碼

字典

與集合相似,字典也是一種存儲謂一值的數據結構,可是以鍵值對的形式來存儲。 ES6中有字典,名爲Map。 字典的經常使用操做:鍵值對的增刪改查。 ​

const s = new Map();

s.set('name', 'rodchen');
s.set('age', '28');

s.get('name'); // 'rodchen'
s.get('age');
s.delete('age');
s.get('age');

// 修改數據值
s.set('name', 'chenyun');

s.clear();
複製代碼

一種分層數據的抽象模型 前端工做中用到的樹結構:DOM樹,樹形控件。

{
  value: 'zhejiang',
  label: 'Zhejiang',
  children: [
    {
      value: 'hangzhou',
      label: 'Hangzhou',
      children: [
        {
          value: 'xihu',
          label: 'West Lake',
        },
      ],
    },
  ],
}
複製代碼

經常使用操做:廣度優先遍歷,深度優先遍歷

圖示網絡結構的抽象模型,是一組由邊連接的節點。 圖能夠表示任何的二元關係,好比道路,航班。 js中沒有圖,經過Object和Array構件圖。 ​

圖的表示法:鄰接矩陣,鄰接表 image.png image.pngimage.png

經常使用操做:廣度優先遍歷,深度優先遍歷

堆是一種徹底二叉樹 從第一層到倒數第二層,每一層都是滿的,也就是說每一層的結點數都達到了當前層所能達到的最大值最後一層的結點是從左到右連續排列的,不存在跳躍排列的狀況(也就是說這一層的全部結點都集中排列在最左邊)。 image.png image.png

下面這種就不行 image.png

輔助知識

數組

ES5及以前方法

建立數組

let colors = new Array();
let colors = new Array(20);
let colors = new Array("red", "blue", "green");
let colors = ["red", "blue", "green"];
複製代碼

判斷數組

value instanceof Array

Array.isArray(value)
複製代碼

轉換方法

全部對象都有 toLocaleString()、toString()和 valueOf()方法。

  • valueOf()返回的仍是數組自己
  • toString()返回由數組中每一個值的等效字符串拼接而成的一個逗號分隔的字符串,內部調用每一個item的toString方法
  • toLocaleString()則是調用每一個item項目的toLocaleString()
let colors = ["red", "blue", "green"];

console.log(colors.toString()); // red,blue,green 
console.log(colors.valueOf()); // red,blue,green 
console.log(colors); //  ["red", "blue", "green"]
複製代碼

棧方法

ECMAScript 數組提供了 push()和 pop()方法,以實現相似棧的行爲。

隊列方法

ECMAScript 數組提供了 push()和 shift()方法,以實現相似棧的行爲。

排序方法

數組有兩個方法能夠用來對元素從新排序:reverse()和 sort()。

操做方法

  • 合併方法:concat
  • 從現有數組截取建立新數組:slice
  • 在現有數組當中刪除 & 新增元素,返回刪除的數組:splice
// slice
let colors = ["red", "green", "blue", "yellow", "purple"]; 
let colors2 = colors.slice(1); 
let colors3 = colors.slice(1, 4); // 返回元素的開始索引和結束索引
alert(colors2); // green,blue,yellow,purple 
alert(colors3); // green,blue,yellow

// splice
let colors = ["red", "green", "blue"]; 
let removed = colors.splice(0,1); // 刪除第一項

alert(colors); // green,blue 
alert(removed); // red,只有一個元素的數組

removed = colors.splice(1, 0, "yellow", "orange"); // 在位置 1 插入兩個元素
alert(colors); // green,yellow,orange,blue 
alert(removed); // 空數組

removed = colors.splice(1, 1, "red", "purple"); // 插入兩個值,刪除一個元素
alert(colors); // green,red,purple,orange,b
複製代碼

搜索和位置方法

indexOf()、lastIndexOf()

  • indexOf()和 includes()方法從數組前頭(第一項)開始向後搜索,而 lastIndexOf()從數組末尾(最後一項)開始向前搜索。
  • indexOf()和 lastIndexOf()都返回要查找的元素在數組中的位置,若是沒找到則返回 -1。
  • includes()返回布爾值,表示是否至少找到一個與指定元素匹配的項。

迭代方法

  • every():對數組每一項都運行傳入的函數,若是對每一項函數都返回 true,則這個方法返回 true。
  • filter():對數組每一項都運行傳入的函數,函數返回 true 的項會組成數組以後返回。
  • forEach():對數組每一項都運行傳入的函數,沒有返回值。
  • map():對數組每一項都運行傳入的函數,返回由每次函數調用的結果構成的數組。
  • some():對數組每一項都運行傳入的函數,若是有一項函數返回 true,則這個方法返回 true。

這些方法都不改變調用它們的數組。

歸併方法

reduce()和 reduceRight()。這兩個方法都會迭代數組的全部項,並在此基礎上構建一個最終返回值。reduce()方法從數組第一項開始遍歷到最後一項。而 reduceRight()從最後一項開始遍歷至第一項。 ​

  • reduce()和 reduceRight()的函數接收 4 個參數:上一個歸併值、當前項、當前項的索引和數組自己。這個函數返回的任何值都會做爲下一次調用同一個函數的第一個參數。
  • 若是沒有給這兩個方法傳入可選的第二個參數(做爲歸併起點值),則第一次迭代將從數組的第二項開始,所以傳給歸併函數的第一個參數是數組的第一項,第二個參數是數組的第二項。
let values = [1, 2, 3, 4, 5]; 
let sum = values.reduce((prev, cur, index, array) => prev + cur);

alert(sum); // 15
複製代碼

ES6+方法

建立數組

from()用於將類數組結構轉換爲數組實例,而 of()用於將一組參數轉換爲數組實例。

from

// 字符串會被拆分爲單字符數組
console.log(Array.from("Matt")); // ["M", "a", "t", "t"] 

// 可使用 from()將集合和映射轉換爲一個新數組
const m = new Map().set(1, 2) 
 .set(3, 4); 
const s = new Set().add(1) 
 .add(2) 
 .add(3) 
 .add(4); 
console.log(Array.from(m)); // [[1, 2], [3, 4]] 
console.log(Array.from(s)); // [1, 2, 3, 4] 

// Array.from()對現有數組執行淺複製
const a1 = [1, 2, 3, 4]; 
const a2 = Array.from(a1); 
console.log(a1); // [1, 2, 3, 4] 
alert(a1 === a2); // false 

// 可使用任何可迭代對象
const iter = { 
 *[Symbol.iterator]() { 
 yield 1; 
 yield 2; 
 yield 3; 
 yield 4; 
 } 
}; 
console.log(Array.from(iter)); // [1, 2, 3, 4]


/* Array.from()還接收第二個可選的映射函數參數。這個函數能夠直接加強新數組的值,而無須像 * 調用 Array.from().map()那樣先建立一箇中間數組。還能夠接收第三個可選參數,用於指定映射函 * 數中 this 的值。但這個重寫的 this 值在箭頭函數中不適用。 */

const a1 = [1, 2, 3, 4]; 
const a2 = Array.from(a1, x => x**2); 
const a3 = Array.from(a1, function(x) {return x**this.exponent}, {exponent: 2}); 

console.log(a2); // [1, 4, 9, 16] 
console.log(a3); // [1, 4, 9, 16]
複製代碼

of

console.log(Array.of(1, 2, 3, 4)); // [1, 2, 3, 4] 
console.log(Array.of(undefined)); // [undefined]
複製代碼

迭代器方法

在 ES6 中,Array 的原型上暴露了 3 個用於檢索數組內容的方法:keys()、values()和entries()。keys()返回數組索引的迭代器,values()返回數組元素的迭代器,而 entries()返回索引/值對的迭代器:

const a = ["foo", "bar", "baz", "qux"]; 

const aKeys = Array.from(a.keys()); 
const aValues = Array.from(a.values()); 
const aEntries = Array.from(a.entries()); 

console.log(aKeys); // [0, 1, 2, 3] 
console.log(aValues); // ["foo", "bar", "baz", "qux"] 
console.log(aEntries); // [[0, "foo"], [1, "bar"], [2, "baz"], [3, "qux"]]
複製代碼

複製 & 填充方法

fill方法

使用 fill()方法能夠向一個已有的數組中插入所有或部分相同的值。開始索引用於指定開始填充的位置,它是可選的。若是不提供結束索引,則一直填充到數組末尾。負值索引從數組末尾開始計算。也能夠將負索引想象成數組長度加上它獲得的一個正索引。

// 用 5 填充整個數組
zeroes.fill(5); 
console.log(zeroes); // [5, 5, 5, 5, 5] 
zeroes.fill(0); // 重置

// 用 6 填充索引大於等於 3 的元素
zeroes.fill(6, 3); 
console.log(zeroes); // [0, 0, 0, 6, 6] 
zeroes.fill(0); // 重置

// 用 7 填充索引大於等於 1 且小於 3 的元素
zeroes.fill(7, 1, 3); 
console.log(zeroes); // [0, 7, 7, 0, 0]; 
zeroes.fill(0); // 重置
複製代碼

copyWithin方法

copyWithin()會按照指定範圍淺複製數組中的部份內容,而後將它們插入到指定索引開始的位置。開始索引和結束索引則與 fill()使用一樣的計算方法

let intArray = [1, 2, 3, 4, 5];

intArray.copyWithin(2, 0, 3); // [1, 2, 1, 2, 3]
複製代碼

搜索和位置方法

includes() ES7 includes()返回布爾值,表示是否至少找到一個與指定元素匹配的項

find & findIndex find()和 findIndex()方法使用了斷言函數。這兩個方法都從數組的最小索引開始。find()返回第一個匹配的元素,findIndex()返回第一個匹配元素的索引。這兩個方法也都接收第二個可選的參數,用於指定斷言函數內部 this 的值。

數組拉平

Array.prototype.flat()用於將嵌套的數組「拉平」,變成一維的數組。flat()默認只會「拉平」一層,若是想要「拉平」多層的嵌套數組,能夠將flat()方法的參數寫成一個整數,表示想要拉平的層數,默認爲1.

[1, 2, [3, [4, 5]]].flat()
// [1, 2, 3, [4, 5]]

[1, 2, [3, [4, 5]]].flat(2)
// [1, 2, 3, 4, 5]

[1, [2, [3]]].flat(Infinity)

複製代碼

flatMap()方法對原數組的每一個成員執行一個函數(至關於執行Array.prototype.map()),而後對返回值組成的數組執行flat()方法。該方法返回一個新數組,不改變原數組。

[2, 3, 4].flatMap((x) => [x, x * 2])
// [2, 4, 3, 6, 4, 8]
複製代碼

字符串

ES5及以前方法

建立字符串

let stringObject = new String("hello world");

let message = "abcde";
複製代碼

合併字符串

concat:用於將一個或多個字符串拼接成一個新字符串。

截取字符串

slice()、substr()和 substring()。

第一個參數表示子字符串開始的位置,第二個參數表示子字符串結束的位置。對 slice()和 substring()而言,第二個參數是提取結束的位置(即該位置以前的字符會被提取出來)。對 substr()而言,第二個參數表示返回的子字符串數量。 ​

let stringValue = "hello world"; 

console.log(stringValue.slice(3)); // "lo world" 
console.log(stringValue.substring(3)); // "lo world" 
console.log(stringValue.substr(3)); // "lo world" 
console.log(stringValue.slice(3, 7)); // "lo w" 
console.log(stringValue.substring(3,7)); // "lo w" 
console.log(stringValue.substr(3, 7)); // "lo worl"
複製代碼

從上面看到slice,substring好像表現的同樣,不一樣的點在於參數是負數。

  • slice()方法將全部負值參數都當成字符串長度加上負參數值。
  • substr()方法將第一個負參數值當成字符串長度加上該值,將第二個負參數值轉換爲 0。
  • substring()方法會將全部負參數值都轉換爲 0。

第一個參數爲負數的時候:

let stringValue = "hello world"; 

console.log(stringValue.slice(-3)); // "rld" 
console.log(stringValue.substring(-3)); // "hello world" 
console.log(stringValue.substr(-3)); // "rld"
複製代碼

兩個參數都是負數的時候:

console.log(stringValue.slice(3, -4)); // "lo w" 
console.log(stringValue.substring(3, -4)); // "hel" 
console.log(stringValue.substr(3, -4)); // "" (empty string)
複製代碼

位置方法

indexOf()和 lastIndexOf()。這兩個方法從字符串中搜索傳入的字符串,並返回位置(若是沒找到,則返回-1)。二者的區別在於,

  • indexOf()方法從字符串開頭開始查找子字符串
  • 而 lastIndexOf()方法從字符串末尾開始查找子字符串
let stringValue = "hello world";

console.log(stringValue.indexOf("o")); // 4 
console.log(stringValue.lastIndexOf("o")); // 7
複製代碼

清空兩邊空格

trim():返回新的字符串

let stringValue = " hello world "; 
let trimmedStringValue = stringValue.trim(); 
console.log(stringValue); // " hello world " 
console.log(trimmedStringValue); // "hello world"
複製代碼

字符串具備@@iterator特性

可以使用for-of和解構操做

for (const c of "abcde") { 
 console.log(c); 
} 
// a 
// b 
// c 
// d 
// e

let message = "abcde"; 
console.log([...message]); // ["a", "b", "c", "d", "e"]
複製代碼

匹配功能

search / match / replace方法,具體可查看以前的文章:juejin.cn/post/697103…

比較方法

localeCompare(),這個方法比較兩個字符串,返回以下 3 個值中的一個。

  • 若是按照字母表順序,字符串應該排在字符串參數前頭,則返回負值。(一般是-1,具體還要看與實際值相關的實現。)
  • 若是字符串與字符串參數相等,則返回 0。 
  • 若是按照字母表順序,字符串應該排在字符串參數後頭,則返回正值。(一般是 1,具體還要看與實際值相關的實現。)

下面是一個例子:

let stringValue = "yellow";

console.log(stringValue.localeCompare("brick")); // 1 
console.log(stringValue.localeCompare("yellow")); // 0 
console.log(stringValue.localeCompare("zoo")); // -1
複製代碼

ES6+方法

包含方法

startsWith()、endsWith()和 includes()。

  • includes():返回布爾值,表示是否找到了參數字符串。
  • startsWith():返回布爾值,表示參數字符串是否在原字符串的頭部。
  • endsWith():返回布爾值,表示參數字符串是否在原字符串的尾部。
let message = "foobarbaz"; 

console.log(message.startsWith("foo")); // true 
console.log(message.startsWith("bar")); // false 
console.log(message.endsWith("baz")); // true 
console.log(message.endsWith("bar")); // false 
console.log(message.includes("bar")); // true 
console.log(message.includes("qux")); // false
複製代碼

重複字符串

repeat方法返回一個新字符串,表示將原字符串重複n次。

'x'.repeat(3) // "xxx"
複製代碼

規則以下:

  • 參數若是是小數,會被取整。
  • 若是repeat的參數是負數或者Infinity,會報錯。可是,若是參數是 0 到-1 之間的小數,則等同於 0,這是由於會先進行取整運算。0 到-1 之間的小數,取整之後等於-0,repeat視同爲 0。
  • 參數NaN等同於 0。
  • 若是repeat的參數是字符串,則會先轉換成數字。

ES8:字符串補全方法

ES2017 引入了字符串補全長度的功能。若是某個字符串不夠指定長度,會在頭部或尾部補全。padStart()用於頭部補全,padEnd()用於尾部補全。

padStart()和padEnd()一共接受兩個參數,第一個參數是字符串補全生效的最大長度,第二個參數是用來補全的字符串。

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

'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'
複製代碼

ES10 移除空格方法

ES2019 對字符串實例新增了trimStart()和trimEnd()這兩個方法。它們的行爲與trim()一致,trimStart()消除字符串頭部的空格,trimEnd()消除尾部的空格。它們返回的都是新字符串,不會修改原始字符串。

const s = ' abc ';

s.trim() // "abc"
s.trimStart() // "abc "
s.trimEnd() // " abc"
複製代碼

正則方法

  • matchAll():返回正則表達式在字符串的全部匹配
  • ES12 replaceAll(): 替換字符串裏全部的匹配項

對象

ES5及以前方法

建立對象

a. 對象直接量 b. 經過new的方式建立對象 c. Object.create() 是一個靜態的方法,而不是提供給某個對象調用的方法。 一個參數是新建對象的原型,第二個爲可選參數,用以對對象的屬性進行說明。

定義屬性

Object.defineProperty() 方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性,並返回此對象。 Object.defineProperties() 方法直接在一個對象上定義新的屬性或修改現有屬性,並返回該對象。

const object1 = {};

Object.defineProperty(object1, 'property1', {
  value: 42,
  writable: false
});

Object.defineProperties(obj, {
  'property1': {
    value: true,
    writable: true
  },
  'property2': {
    value: 'Hello',
    writable: false
  }
});
複製代碼

檢測屬性

  • hasOwnProperty 判斷一個屬性是定義在對象自己仍是繼承自原型鏈。自身對象返回true,繼承屬性返回false。
  • propertyIsEnumable 是hasOwnProperty()的加強版,只有檢測是自有屬性的可枚舉性,若是是自有屬性而且可枚舉的返回true。

查詢自有可枚舉屬性

Object.keys() 獲取自有屬性中枚舉屬性的合集字符串

查詢自有屬性屬性

Object.getOwnPropertyDescriptor()方法返回指定對象上一個自有屬性對應的屬性描述符。(自有屬性指的是直接賦予該對象的屬性,不須要從原型鏈上進行查找的屬性)

var o, d;

o = { get foo() { return 17; } };
d = Object.getOwnPropertyDescriptor(o, "foo");
// d {
// configurable: true,
// enumerable: true,
// get: /*the getter function*/,
// set: undefined
// }
複製代碼

Object.getOwnPropertyNames()方法返回一個由指定對象的全部自身屬性的屬性名(包括不可枚舉屬性但不包括Symbol值做爲名稱的屬性)組成的數組。

var arr = ["a", "b", "c"];
console.log(Object.getOwnPropertyNames(arr).sort()); // ["0", "1", "2", "length"]
複製代碼

原型操做

isPrototypeOf(): p.isPrototypeOf(o) 用來檢測p是不是o的原型。

function Foo() {}
function Bar() {}
function Baz() {}

Bar.prototype = Object.create(Foo.prototype);
Baz.prototype = Object.create(Bar.prototype);

var baz = new Baz();

console.log(Baz.prototype.isPrototypeOf(baz)); // true
console.log(Bar.prototype.isPrototypeOf(baz)); // true
console.log(Foo.prototype.isPrototypeOf(baz)); // true
console.log(Object.prototype.isPrototypeOf(baz)); // true
複製代碼

ES6+方法

合併對象

Object.assign() 方法用於將全部可枚舉屬性的值從一個或多個源對象分配到目標對象。它將返回目標對象。

dest = {}; 
src = { id: 'src' }; 
result = Object.assign(dest, src); 
// Object.assign 修改目標對象
// 也會返回修改後的目標對象
console.log(dest === result); // true 
console.log(dest !== src); // true 
console.log(result); // { id: src } 
console.log(dest); // { id: src }


dest = {}; 
result = Object.assign(dest, { a: 'foo' }, { b: 'bar' }); 
console.log(result); // { a: foo, b: bar }
複製代碼

判斷相等

Object.is() ECMAScript 6 規範新增了 Object.is(),這個方法與===很像,但同時也考慮到了上述邊界情形。這個方法必須接收兩個參數: 不一樣之處只有兩個:一是+0不等於-0,二是NaN等於自身

+0 === -0 //true
NaN === NaN // false

Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
複製代碼

查詢屬性

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

const obj = {
  foo: 123,
  get bar() { return 'abc' }
};

Object.getOwnPropertyDescriptors(obj)
// { foo:
// { value: 123,
// writable: true,
// enumerable: true,
// configurable: true },
// bar:
// { get: [Function: get bar],
// set: undefined,
// enumerable: true,
// configurable: true } }
複製代碼

原型操做

Object.getPrototypeOf() 方法返回指定對象的原型(內部[[Prototype]]屬性的值)。 Object.setPrototypeOf() 方法設置一個指定的對象的原型 ( 即, 內部[[Prototype]]屬性)到另外一個對象或null。

// 格式
Object.setPrototypeOf(object, prototype)
Object.getPrototypeOf(obj);

// 用法
const o = Object.setPrototypeOf({}, null);
複製代碼

Object.setPrototypeOf方法的做用與__proto__相同,用來設置一個對象的原型對象(prototype)。

迭代器方法

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

const obj = { foo: 'bar', baz: 42 };
Object.keys(obj)
// ["foo", "baz"]

Object.values(obj)
// ["bar", 42]

Object.entries(obj)
// [ ["foo", "bar"], ["baz", 42] ]
複製代碼

ES6運算符擴展

指數運算符

ES2016 新增了一個指數運算符(**)

2 ** 2 // 4
2 ** 3 // 8

// 右結合運算 至關於 2 ** (3 ** 2)
2 ** 3 ** 2
// 512
複製代碼

鏈判斷運算符

編程實務中,若是讀取對象內部的某個屬性,每每須要判斷一下,屬性的上層對象是否存在。 ES2020 引入了「鏈判斷運算符」(optional chaining operator)?.,簡化上面的寫法。

const firstName = message?.body?.user?.firstName || 'default';
const fooValue = myForm.querySelector('input[name=foo]')?.value
複製代碼

NUll判斷運算符

讀取對象屬性的時候,若是某個屬性的值是null或undefined,有時候須要爲它們指定默認值。常見作法是經過||運算符指定默認值。可是屬性的值若是爲空字符串或false或0,默認值也會生效。 ​

ES2020 引入了一個新的 Null 判斷運算符??。它的行爲相似||,可是隻有運算符左側的值爲null或undefined時,纔會返回右側的值。

const headerText = response.settings.headerText ?? 'Hello, world!';
const animationDuration = response.settings.animationDuration ?? 300;
const showSplashScreen = response.settings.showSplashScreen ?? true;
複製代碼

??本質上是邏輯運算,它與其餘兩個邏輯運算符&&和||有一個優先級問題,它們之間的優先級到底孰高孰低。若是多個邏輯運算符一塊兒使用,必須用括號代表優先級,不然會報錯。

邏輯賦值運算符

// 或賦值運算符
x ||= y
// 等同於
x || (x = y)

// 與賦值運算符
x &&= y
// 等同於
x && (x = y)

// Null 賦值運算符
x ??= y
// 等同於
x ?? (x = y)



// 老的寫法
user.id = user.id || 1;

// 新的寫法
user.id ||= 1;
複製代碼

學習路線

來源於Lucifer在早早聊的分享其中的一頁ppt。

  • 複雜度分析:如何衡量算法的性能
  • 基礎的數據結構:線性數據結構 (數組,鏈表,棧,隊列,哈希表)
  • 基礎的數據結構:非線形數據結構 (樹,圖)
  • 排序算法:經典排序算法
  • 遞歸:一種高級的思惟技巧
  • 暴力搜索篇:回溯,BFS,DFS
  • 暴力優化篇:剪枝,滑動窗口,雙指針,單調棧
  • 高級搜索篇:二分法和位運算
  • 動態規劃篇:記憶化搜索與動態規劃
  • 分治:大事化小,小事化小
  • 貪心:簡單高效但不靠譜的算法
  • 逆向思考

算法的掌握程度

來源於葉濛濛在早早聊分享的知識,也是一種自我在對於算法掌握的層次考量。

  • 據說
    • 知道名稱和功能
  • 瞭解
    • 知道原理和優缺點
  • 理解
    • 知道過程和實現細節
    • 能描述數據結構和控制流程
    • 知道時空複雜度
  • 實現
    • 可以編程實現
  • 應用
    • 可以運⽤解決實際問題
相關文章
相關標籤/搜索