这是我参与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。
来源于叶蒙蒙在早早聊分享的知识,也是一种自我在对于算法掌握的层次考量。