這是我參與8月更文挑戰的第3天,活動詳情查看:8月更文挑戰javascript
在數學中,對數是對求冪的逆運算,正如除法是乘法的逆運算,反之亦然。 [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
}
複製代碼
一組無序且惟一的數據結構。 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構件圖。
圖的表示法:鄰接矩陣,鄰接表
經常使用操做:廣度優先遍歷,深度優先遍歷
堆是一種徹底二叉樹 從第一層到倒數第二層,每一層都是滿的,也就是說每一層的結點數都達到了當前層所能達到的最大值最後一層的結點是從左到右連續排列的,不存在跳躍排列的狀況(也就是說這一層的全部結點都集中排列在最左邊)。
下面這種就不行
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()方法。
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()。
// 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()
這些方法都不改變調用它們的數組。
reduce()和 reduceRight()。這兩個方法都會迭代數組的全部項,並在此基礎上構建一個最終返回值。reduce()方法從數組第一項開始遍歷到最後一項。而 reduceRight()從最後一項開始遍歷至第一項。
let values = [1, 2, 3, 4, 5];
let sum = values.reduce((prev, cur, index, array) => prev + cur);
alert(sum); // 15
複製代碼
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]
複製代碼
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好像表現的同樣,不一樣的點在於參數是負數。
第一個參數爲負數的時候:
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)。二者的區別在於,
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"
複製代碼
可以使用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 個值中的一個。
下面是一個例子:
let stringValue = "yellow";
console.log(stringValue.localeCompare("brick")); // 1
console.log(stringValue.localeCompare("yellow")); // 0
console.log(stringValue.localeCompare("zoo")); // -1
複製代碼
startsWith()、endsWith()和 includes()。
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"
複製代碼
規則以下:
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'
複製代碼
ES2019 對字符串實例新增了trimStart()和trimEnd()這兩個方法。它們的行爲與trim()一致,trimStart()消除字符串頭部的空格,trimEnd()消除尾部的空格。它們返回的都是新字符串,不會修改原始字符串。
const s = ' abc ';
s.trim() // "abc"
s.trimStart() // "abc "
s.trimEnd() // " abc"
複製代碼
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
}
});
複製代碼
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
複製代碼
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] ]
複製代碼
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或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。
來源於葉濛濛在早早聊分享的知識,也是一種自我在對於算法掌握的層次考量。