对象
----prototype对象
Object.setPrototypeOf(object, prototype) 设置一个对象的prototype(原型)对象
Object.getPrototypeOf(obj) 用于读取一个对象的prototype对象
----获取该属性的描述对象
let obj = { foo: 123 };
Object.getOwnPropertyDescriptor(obj, 'foo')
--enumerable属性,称为”可枚举性“,如果该属性为false,就表示某些操作会忽略当前属性
----比较两个值是否严格相等
Object.is('foo', 'foo')
----对象的合并
Object.assign(target,...source) 将源对象(source)的所有可枚举属性,复制到目标对象(target),实行的是浅拷贝
-- 为对象添加属性
class Point {
constructor(x, y) {
Object.assign(this, {x, y});
}
}
--为对象添加方法
Object.assign(SomeClass.prototype, {
someMethod(arg1, arg2) {
···
},
anotherMethod() {
···
}
});
// 等同于下面的写法
SomeClass.prototype.someMethod = function (arg1, arg2) {
···
};
--对象拷贝(深层次拷贝)
function clone(origin) {
let originProto = Object.getPrototypeOf(origin);
return Object.assign(Object.create(originProto), origin);
}
--属性的遍历
(1)for...in
for...in循环遍历对象自身的和继承的可枚举属性(不含Symbol属性)。
(2)Object.keys(obj)
Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性)。
(3)Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性)。
(4)Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有Symbol属性。
(5)Reflect.ownKeys(obj)
Reflect.ownKeys返回一个数组,包含对象自身的所有属性,不管是属性名是Symbol或字符串,也不管是否可枚举。
函数
name属性,返回该函数的函数名
bind()方法主要就是将函数绑定到某个对象
foo::bar;
// 等同于
bar.bind(foo);
foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);
----尾递归优化
function tco(f) {
var value;
var active = false;
var accumulated = [];
return function accumulator() {
accumulated.push(arguments);
if (!active) {
active = true;
while (accumulated.length) {
value = f.apply(this, accumulated.shift());
}
active = false;
return value;
}
};
}
var sum = tco(function(x, y) {
if (y > 0) {
return sum(x + 1, y - 1)
}
else {
return x
}
});
sum(1, 100000)
数组
Array.from() 将类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构Set和Map)转为真正的数组
Array.of() 用于将一组值,转换为数组。
copyWithin() 在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组
find() 用于找出第一个符合条件的数组成员
findIndex() 返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1
fill() 方法使用给定值,填充一个数组。
includes() 方法返回一个布尔值,表示某个数组是否包含给定的值
数值
----常用方法
Number.isFinite() =》用来检查一个数值是否为有限的(finite)
Number.isNaN() =》 用来检查一个值是否为NaN
Number.parseInt() =》
Number.parseFloat() =》
Number.isInteger() =》用来判断一个值是否为整数
Number.EPSILON =》 是一个可以接受的误差范围。
Math.trunc() 用于去除一个数的小数部分,返回整数部分
Math.sign 用来判断一个数到底是正数、负数、还是零
Math.cbrt 用于计算一个数的立方根。
Math.clz32 返回一个数的32位无符号整数形式有多少个前导0
Math.hypot 返回所有参数的平方和的平方根。
字符串
----字符串常用方法
match() =》 在字符串内检索指定的值,或找到一个或多个正则表达式的匹配
replace() =》 在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串
search() =》 检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。
split() =》 把一个字符串分割成字符串数组
length =》 获取字符串长度
charAt() =》 获取字符串某位字符
charCodeAt() =》 返回指定索引位置字符的 Unicode 值
fromCharCode() =》 将 Unicode 转换为字符串
indexOf()=》 查找某个字符,有则返回第一次匹配到的位置,否则返回-1
lastIndexOf() =》 查找某个字符,有则返回最后一次匹配到的位置,否则返回-1
concat() =》 将指定的字符串参数连接到字符串上
substr() =》 从起始索引号提取字符串中指定数目的字符
substring() =》 提取字符串中两个指定的索引号之间的字符
slice() =》 提取字符串的片断,并在新的字符串中返回被提取的部
toLowerCase() =》 把字符串转换为小写
toUpperCase() =》 把字符串转换为大写
trim() =》 用于移除字符串首尾空白
valueOf() =》 返回某个字符串对象的原始值
toString() =》 返回字符串对象本身
trimStart() =》 消除字符串头部的空格
trimEnd() =》 消除尾部的空格
----codePointAt测试一个字符由两个字节
function is32Bit(c) {
return c.codePointAt(0) > 0xFFFF;
}
is32Bit("????") // true
is32Bit("a") // false
----字符串的遍历
for (let codePoint of 'foo') {
console.log(codePoint)
}
----确定一个字符串是否包含在另一个字符串中
includes():返回布尔值,表示是否找到了参数字符串。
startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。
endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。
----将原字符串重复n次
'hello'.repeat(2)
----字符串补全长度
'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'
----模板字符串
用反引号(`)标识
// 字符串中嵌入变量
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
JS内置对象
---------------值属性----------------全局属性返回一个简单值
Infinity =======> 全局属性 Infinity 是一个数值,表示无穷大。
NaN =======> 全局属性 NaN 的值表示不是一个数字
undefined =======> 全局属性undefined表示原始值undefined。它是一个JavaScript的 原始数据类型
globalThis =======> 全局属性 globalThis 包含全局的 this 值,类似于全局对象(global object)。
---------------函数属性----------------全局函数可以直接调用,不需要在调用时指定所属对象,执行结束后会将结果直接返回给调用者。
eval() =======> eval() 函数会将传入的字符串当做 JavaScript 代码进行执行。 永远不要使用 eval!
isFinite() =======> 该全局 isFinite() 函数用来判断被传入的参数值是否为一个有限数值(finite number)如果参数是 NaN,正无穷大或者负无穷大,会返回false,其他返回 true。
isNaN() =======> isNaN() 函数用来确定一个值是否为NaN
parseFloat() =======> parseFloat() 函数解析一个参数(必要时先转换为字符串)并返回一个浮点数。
parseInt() =======> parseInt(string, radix) 解析一个字符串并返回指定基数的十进制整数, radix 是2-36之间的整数,表示被解析字符串的基数(进制)。
decodeURI() =======> decodeURI() 函数能解码由encodeURI 创建或其它流程得到的统一资源标识符(URI)
decodeURIComponent() =======>
encodeURI() =======> encodeURI() 函数通过将特定字符的每个实例替换为一个、两个、三或四转义序列来对统一资源标识符 (URI) 进行编码 (该字符的 UTF-8 编码仅为四转义序列)由两个 "代理" 字符组成)。
encodeURIComponent() =======>
---------------基本对象---------------- 基本对象是定义或使用其他对象的基础
Set和Map数据结构
---------------Set----------------类似于数组,但是成员的值都是唯一的,没有重复的值。
Set.prototype.constructor => 构造函数,默认就是Set函数。
Set.prototype.size => 返回Set实例的成员总数。
add(value) => 添加某个值,返回Set结构本身。
delete(value) => 删除某个值,返回一个布尔值,表示删除是否成功。
has(value) => 返回一个布尔值,表示该值是否为Set的成员。
clear() => 清除所有成员,没有返回值。
-----遍历方法 ---Set的遍历顺序就是插入顺序,Set结构键名和键值是同一个值
keys() => 返回键名的遍历器
values() => 返回键值的遍历器
entries() => 返回键值对的遍历器
forEach() => 使用回调函数遍历每个成员
var s = new Set();
[2, 3, 5, 4, 5, 2, 2].map(x => s.add(x)); // map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。
for (let i of s) {
console.log(i);
}
// 2 3 5 4
// 去除数组的重复成员
[...new Set(array)]
//两个对象总是不相等的
let set = new Set();
set.add({});
set.size // 1
set.add({});
set.size // 2
将Set结构转为数组
var items = new Set([1, 2, 3, 4, 5]);
var array = Array.from(items);
---Set实现并集(Union)、交集(Intersect)和差集(Difference)。
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
// 并集
let union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}
// 交集
let intersect = new Set([...a].filter(x => b.has(x)));
// set {2, 3}
// 差集
let difference = new Set([...a].filter(x => !b.has(x)));
// Set {1}
---------------Map---------------- 值—值”的对应的Hash结构实现,键”的范围不在限于字符串,各种类型的值(包括对象)都可以当作键
size => 属性返回Map结构的成员总数。
set(key, value) => 设置key所对应的键值,然后返回整个Map结构。如果key已经有值,则键值会被更新,否则就新生成该键
get(key) => 读取key对应的键值,如果找不到key,返回undefined。
has(key) => 返回一个布尔值,表示某个键是否在Map数据结构中。
delete(key) => 删除某个键,返回true。如果删除失败,返回false。
clear() => 清除所有成员,没有返回值。
-----遍历方法 ---Map的遍历顺序就是插入顺序
keys() => 返回键名的遍历器。
values() => 返回键值的遍历器。
entries() => 返回所有成员的遍历器。
forEach() => 遍历Map的所有成员。
-----Map结构转为数组结构
let map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
[...map.keys()]
// [1, 2, 3]
[...map.values()]
// ['one', 'two', 'three']
[...map.entries()]
// [[1,'one'], [2, 'two'], [3, 'three']]
[...map]
// [[1,'one'], [2, 'two'], [3, 'three']]
----Map的遍历和过滤
let map0 = new Map()
.set(1, 'a')
.set(2, 'b')
.set(3, 'c');
let map1 = new Map(
[...map0].filter(([k, v]) => k < 3)
);
// 产生Map结构 {1 => 'a', 2 => 'b'}
let map2 = new Map(
[...map0].map(([k, v]) => [k * 2, '_' + v])
);
// 产生Map结构 {2 => '_a', 4 => '_b', 6 => '_c'}
-----Map结构转换
(1)Map转为数组 =》let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);[...myMap]
(2)数组转为Map =》new Map([[true, 7], [{foo: 3}, ['abc']]])
(3)Map转为对象(所有Map的键都是字符串) =>
function strMapToObj(strMap) {
let obj = Object.create(null);
for (let [k,v] of strMap) {
obj[k] = v;
}
return obj;
}
(4)对象转为Map
function objToStrMap(obj) {
let strMap = new Map();
for (let k of Object.keys(obj)) {
strMap.set(k, obj[k]);
}
return strMap;
}
(5)Map转为JSON
---Map的键名都是字符串
function strMapToJson(strMap) {
return JSON.stringify(strMapToObj(strMap));
}
---Map的键名有非字符串
function mapToArrayJson(map) {
return JSON.stringify([...map]);
}
(6)JSON转为Map
function jsonToStrMap(jsonStr) {
return objToStrMap(JSON.parse(jsonStr));
}
JS 页面路由
---------window.open()与window.location.href的区别--------------
window.open('index.html') // 表示新增一个窗口打开 index.html 这个页面,并不刷新
window.location.href="./index.html"; // 在原窗口打开新页面
---------window.open--------------
window.open ('page.html', 'newwindow', 'height=100, width=400, top=0, left=0, toolbar=no, menubar=no, scrollbars=no, resizable=no,location=n o, status=no')
参数解释: 三个参数
window.open 弹出新窗口的命令;
'page.html' 弹出窗口的文件名;
'newPage' 弹出窗口的名字(不是文件名),非必须,可用空’'代替;
height=100 窗口高度;
width=400 窗口宽度;
top=0 窗口距离屏幕上方的象素值;
left=0 窗口距离屏幕左侧的象素值;
toolbar=no 是否显示工具栏,yes 为显示;
menubar=no 是否显示菜单栏,yes 为显示;
scrollbars=no 是否显示滚动栏,yes 为显示;
resizable=no 是否允许改变窗口大小,yes 为允许;
location=no 是否显示地址栏,yes 为允许;
status=no 是否显示状态栏内的信息(通常是文件已经打开),yes为允许;
---------路由操作--------------
history.back(-1) //返回上一页
history.go(-1) //返回上一页
history.go(-2) //返回前两页
location.reload() //刷新当前页面
self.location=document.referrer; //返回上一页并刷新
代码优化方案
-
非 null
或
undefined 赋值const test= null ?? 'default string'; //空值合并操作符(??)是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。 --------> default string const test2= undefined || { value:'default string'}; --------->{value: "default string"} const test3= 0 || ["value" ,'default string']; -----------> ["value", "default string"] const test4= 0 ?? ["value" ,'default string']; -----------> 0
-
if 多条件判断
if(test === '1' || test === '2' || test === '3' || test === '4'){ // 逻辑 } // 优化后 if(['1','2','3','4'].includes(test)){ // 逻辑处理 } ------------------------------------ let test = null; if(a > 10) { test = true; } else { test = false; } // 优化后 let test = a > 10 ? true : false; // 或者 let test = a > 10; ------------------------------------ if (test1 === true) if (test1 !== "") if (test1 !== null) // 优化 if (test1) ------------------------------------ if (test) { foo(); } //优化 test && foo();
-
Switch
switch (type) { case 1: test1(); break; case 2: test2(); break; case 3: test(); break; // ...... } // 优化 var obj = { 1: test1, 2: test2, 3: test }; obj[type] && obj[type]();
-
数组
------------数组合并----------- const data1 = [1, 2, 3]; const data2 = [4 ,5 , 6].concat(data1); // 优化 const data2 = [4 ,5 , 6, ...data1]; data2.push(...data1) ------------数组克隆----------- const data1 = [1, 2, 3]; const data2 = test1.slice() // 优化 const data1 = [1, 2, 3]; const data2 = [...data1];
-
字符串
const text1 = ‘aa’ const test = 'hello ' + text1 + '.' // 优化 const test = `hello ${text}.`
-
数据赋值与解构
------------多变量赋值----------- let a = 1; let b = 2; let c = 3; // 优化 let [a, b, c] = [1, 2, 3]; ------------数据解构----------- const a1 = this.data.a1; const a2 = this.data.a2; const a3 = this.data.a3; // 优化 const { a1, a2, a3 } = this.data;
-
Object
obj = {100 : "a", 2 : "b", 7 : "c"}; // 数字作为对象属性,自动排序 ------------Object.keys()----------- ---处理对象,返回一个表示给定对象的所有可枚举*属性*的字符串数组 let person = {name:"张三",age:25,address:"深圳",getName:function(){}}; console.log(Object.keys(person)); // ["name", "age", "address", "getName"] ---处理数组,返回索引值数组 let arr = [1,2,3,4,5,6]; console.log(Object.keys(arr)); //["0", "1", "2", "3", "4", "5"] ---处理字符串,返回索引值数组 let str = "ikun你好"; console.log(Object.keys(str)); // ["0", "1", "2", "3", "4", "5"] ---使用 let person = {name:"张三",age:25,address:"深圳",getName:function(){}}; Object.keys(person).map((key)=>{ console.log(person[key]); // 获取到属性对应的值,做一些处理 }) ------------Object.values()----------- --返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历属性的值 let obj = { foo : "bar", baz : 20 }; console.log(Object.values(obj)); // ["bar", 20] ------------Object.entries()----------- ---处理对象,方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组 const data = { a1: 'abc', a2: 'cde', a3: 'efg' }; Object.entries(data); /** 输出: [ [ 'a1', 'abc' ], [ 'a2', 'cde' ], [ 'a3', 'efg' ] ] **/ --将对象转为真正的Map结构 const map = new Map(Object.entries(obj));
-
计算
------------求平方----------- Math.pow(2,3); // 优化 2**3; ------------指数----------- let a = 10000 // 优化 let a = 1e4 ------------字符串转数字----------- let a1 = parseInt('100'); let a2 = parseFloat('10.1'); // 简写 let a1 = +'100'; let a2 = +'10.1';
-
方法收集
--------- 异步引入script async function loadScript(url){ return new Promise((resolve,reject)=>{ let script = document.createElement('script'); script.src = url; script.onload = resolve; script.onerror = reject; document.head.appendChild(script); }) } ----rest参数优化数组push方法 function arrPush(array, ...items) { items.forEach(function(item) { array.push(item); }); return array; } ----求一个数组最大元素 Math.max(...[14, 3, 77]) ----字符串转单字符数组 [...'hello'] ----为不具备 Iterator 接口的对象提供遍历方法 function* objectEntries(obj) { const propKeys = Reflect.ownKeys(obj); for (const propKey of propKeys) { yield [propKey, obj[propKey]]; } } const jane = { first: 'Jane', last: 'Doe' }; for (const [key,value] of objectEntries(jane)) { console.log(`${key}: ${value}`); } ----尾递归优化 function tco(f) { var value; var active = false; var accumulated = []; return function accumulator() { accumulated.push(arguments); if (!active) { active = true; while (accumulated.length) { value = f.apply(this, accumulated.shift()); } active = false; return value; } }; } var sum = tco(function(x, y) { if (y > 0) { return sum(x + 1, y - 1) } else { return x } }); sum(1, 100000)