数据类型
字符串
str.toString('进制')
str.charAt(index)
或str[index]
:返回索引对应的字符str.concat(str1,str2,str3...)
str.indexOf()
或str.lastIndexOf()
; // 返回索引或-1str.trim()
: 去除字符串两边的空格str.toUpperCase()
:转换大写str.toLowerCase()
:转换小写str.replace(oldStr,newStr)
:字符串替换str.split('...')
: 把一个字符串分割成字符串数组for···of···
: 字符串的遍历器接口includes() startsWith() endsWith()
padStart() padEnd()
: 字符串补全repeat(num)
: 将源字符串复制 num 遍,返回新的字符串
// 字符串.slice(start, end); // 前包后不包
// slice() substring() substr() 第一个参数是开始位置,
// slice() substring() 第二个参数是结束位置
// substr() 第二个参数是 返回的长度
let str = abcdefg;
console.log(str.slice(2, 4)); // cd
console.log(str.substring(2, 4)); // cd
console.log(str.substr(2, 4)); // cdef
数组
ES5 数组方法
// 检测数组
Array.isArray(arr);
arr instanceof Array;
// 转换方法
arr.toLocaleString();
arr.toString();
arr.valueOf();
// 栈方法(后进先出)
arr.push(item1,item2,....,itemx); // 添加元素,返回值为数组的长度,并且原数组会发生变化
arr.pop(item1,item2,....,itemx); // 删除并返回数组的最后一个元素,原数组会发生变化
// 队列方法(先进先出)
arr.unshift(newelement1,newelement2,....,newelementX); // 向数组的开头添加一个或更多元素,并返回新的长度。【原数组会发生变化】
arr.shift(); // 删除并返回数组的第一个元素 【原数组会发生变化】
// 颠倒数组中元素的顺序。返回颠倒后的数组 【原数组会发生变化】
arr.reverse();
// 对数组的元素进行排序
arr.sort(); // 默认排序顺序是根据字符串 Unicode 编码
arr.sort(function (a, b) {
return a - b; // 升序(从小到大)
});
arr.sort(function (a, b) {
return b - a; // 降序(从大到小)
});
// 数组拼接
arr.concat(arr01,arr02,...) // 返回新的数组
// 数组拼接
arr.join(separator);
// 从已有的数组中返回选定的元素。【截取后,不会改变原数组,而是返回新的数组】
arr.slice(start,end); // 只有 start,将会截取到数组末尾
// 如果 start 的值为负数,假如数组长度为 length,则表示从 length+start 的位置开始复制,
// 此时参数 end 如果有值,只能是比 start 大的负数,否则将返回空数组。
[1,2,3].slice(-1); // [3]
// 向/从数组中添加/替换项目,然后返回被替换出来的项目。【原数组会发生变化】
arr.splice(index, howmany, item1, ..., itemX)
// 参数:
// index 从哪个索引位置开始删 数字
// howmany 替换几个 数字
// item1,.....,itemX 替换的数据(可以是多个) 可选
// 返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1
arr.indexOf(searchElement);
// 返回指定元素在数组中的最后一个的索引,如果不存在则返回 -1。从数组的后面向前查找
arr.lastIndexOf(searchElement);
ES6 数组方法
// 数组遍历
array.forEach(function (value, index, currentArray) {});
// 过滤出符合筛选条件的元素,返回一个新的数组
array.filter(function (value, index, currentArray) {
return 条件;
});
// 验证数组中的每一个元素是否都符合指定的条件,返回布尔值
array.every(function (value, index, currentArray) {
return 条件;
});
// 验证数组中的元素,是否有符合指定条件的,返回布尔值
array.some(function (value, index, currentArray) {
return 条件;
});
// 遍历数组中的每一个元素,更改后存入一个新的数组中,返回一个新的数组
array.map(function (value, index, currentArray) {
return 操作;
});
array.reduce(callback(previousValue, currentValue, index, array)[, initialValue])
copyWithin()
复制数组项
// 数组实例的copyWithin()方法会在当前数组内部将指定位置的成员复制到其他位置(会覆盖原成员),返回新数组
// Array.prototype.copyWithin(target, start = 0, end = this.length)
// target 可选,从该位置替换数据
// start 可选,从该位置读取数据,默认是0
// end 可选,到该位置前停止读取数据,默认等于数组长度。如果是负值,表示倒数
find() 和 findIndex()
// .find() 找出第一个符合条件的数组成员,参数是一个回调函数
// 所有数组成员一次执行该回调函数,直到找到第一个返回为true的成员,然后返回该成员
// 如果么有符合从条件的成员,则返回undefined。 findIndex() 返回 索引
fill()
给定值填充到一个数组中,返回值为新数组entries() keys() values()
-- 用于遍历数组includes()
方法返回的是一个布尔值,表示数组是否包含给定的值Array.from()
将类数组对象转化为真正的数组Array.of()
将一组值转化为数组
数组的空位
// 空位不是 `undefined`
console.log(Array(3)); // [empty × 3]
forEach()
、filter()
、every()
和some()
都会跳过空位map()
会跳过空位,但是会保留这个值join()
和toString()
会将空位视为undefined
- 而
undefined
和null
会被处理成空字符串 ES6
明确将空位转化为undefined
对象
Object.assign(target, ...sources)
:将一个或多个源对象的所有可枚举属性复制到目标对象,并返回目标对象。Object.create(proto, [propertiesObject])
:使用指定的原型对象和可选的属性对象创建一个新对象。Object.defineProperty(obj, prop, descriptor)
:将一个属性添加到对象或修改现有属性的特性。Object.defineProperties(obj, props)
:将多个属性添加到对象或修改现有属性的特性。Object.entries(obj)
:返回一个给定对象自身可枚举属性的键值对数组。Object.freeze(obj)
:冻结一个对象,使其不可修改,包括属性和原型。Object.fromEntries(iterable)
:将一个键值对数组转换为一个对象。Object.getOwnPropertyDescriptor(obj, prop)
:返回指定对象上一个自有属性对应的属性描述符。Object.getOwnPropertyDescriptors(obj)
:返回指定对象上所有自有属性对应的属性描述符。Object.getOwnPropertyNames(obj)
:返回一个数组,包含指定对象所有自有属性的名称。Object.getOwnPropertySymbols(obj)
:返回一个数组,包含指定对象所有自有 Symbol 类型属性的 Symbol 值。Object.getPrototypeOf(obj)
:返回指定对象的原型。Object.is(value1, value2)
:比较两个值是否相等,与===
运算符不同,Object.is()
方法认为NaN
和-0
是不同的。Object.keys(obj)
:返回一个数组,包含指定对象所有自有可枚举属性的名称。Object.preventExtensions(obj)
:阻止一个对象扩展,使其不能添加新属性。Object.seal(obj)
:封闭一个对象,使其不能添加新属性,同时将所有现有属性设置为不可配置。Object.setPrototypeOf(obj, proto)
:设置一个对象的原型为另一个对象或null
。Object.values(obj)
:返回一个数组,包含指定对象所有自有可枚举属性的值。Object.isExtensible()
方法判断一个对象是否是可扩展的(是否可以在它上面添加新的属性),返回值:表示给定对象是否可扩展的一个 Boolean。
属性描述符
JavaScript 中的属性描述符(Property Descriptor)是一个包含对象属性相关信息的数据结构,它可以用来定义和控制属性的行为和特性。每个对象属性都有一个相关的属性描述符,可以通过 Object.getOwnPropertyDescriptor()
方法来获取该属性的描述符。
Object.defineProperty()
Object.defineProperty()` 是 JavaScript 中一个非常重要的方法,它可以用来定义对象属性的行为和特性。具体来说,它可以用来实现以下功能:
- 定义新的对象属性或修改已有属性的特性:通过
Object.defineProperty()
方法,我们可以重新定义一个对象的已有属性或者创建一个新的属性,并指定该属性的特性(例如是否可读写、是否可枚举、是否可删除等)。 - 实现数据绑定或拦截器:通过在属性描述符中定义
get
和set
访问器方法,我们可以实现数据绑定或拦截器,即在属性值被获取或设置时执行一些自定义逻辑。 - 禁止对象扩展或密封:通过属性描述符的
configurable
属性,我们可以禁止对象的扩展或密封,从而防止新属性的添加、已有属性的删除或属性特性的修改。
需要注意的是,Object.defineProperty()
方法只能对对象的直接属性进行操作,而不能对对象的原型链属性进行操作。如果想要对整个对象或对象的原型链进行操作,可以使用其他方法,例如 Object.defineProperties()
、Object.create()
、Object.setPrototypeOf()
等。
如何判断对象上是否包含某个属性
in
操作符:in
操作符会检查属性是否在对象及其原型链中。Object.hasOwnProperty()
方法只会检查属性是否在对象上,不会检查原型链。Object.getPrototypeOf()
方法可以用来获取一个对象的原型对象。如果一个属性不在对象自身的属性列表中,可以使用该方法来判断该属性是否在原型链上。Object.prototype.hasOwnProperty.call()
方法
Object.prototype.hasOwnProperty.call()
方法可以用来判断一个属性是否在对象的原型链上。具体做法是使用 call()
方法将 Object.prototype.hasOwnProperty()
方法绑定到对象上,并将属性名作为参数传入该方法。
const obj = {};
console.log(Object.prototype.hasOwnProperty.call(obj, 'toString')); // false
遍历对象属性的方法
for...in
循环:使用for...in
循环可以遍历对象自身及其原型链上的所有可枚举属性,因此需要使用Object.hasOwnProperty()
方法来判断属性是否是对象自身的属性。Object.keys()
方法:Object.keys()
方法可以返回一个数组,该数组包含对象自身的所有可枚举属性的属性名。因此,可以使用该方法来遍历对象自身的属性。Object.getOwnPropertyNames()
方法:该方法可以返回一个数组,该数组包含对象自身的所有属性的属性名,无论它们是否可枚举。因此,可以使用该方法来遍历对象自身的所有属性。
Symbol
概述
为了减少对象的属性名冲突,ES6 引入新的原始数据类型 Symbol,JS 的第七种数据类型。
Symbol
能够保证每个属性的名字都是独一无二,这样就能从根本上防止属性名冲突。
Symbol
值能够通过Symbol
函数生成,也就是说,对象的属性名现在可以有 2 种类型,一种就是原来的字符串,另一种就是新增的Symbol
类型。
Symbol
函数前不使用new
命令,因为生成的Symbol
是一个原始类型的值,不是对象,那么,也就不能添加属性(类似于字符串的数据类型)Symbol
函数乐意接受一个字符串作为参数,表示Symbol
实例的描述,主要是为了在控制台显示,或者转化为字符串为了区分(注意,相同参数返回值是不相同的!)
let s1 = Symbol('s1');
let s2 = Symbol('s2');
let s3 = Symbol('s2');
console.log(s1, s2); // Symbol(s1) Symbol(s2)
console.log(s1.toString(), s2.toString()); // Symbol(s1) Symbol(s2)
console.log(s2 == s3); // false
console.log(s2 === s3); // false
作为属性名的 Symbol
Symbol 值可以作为标识符用于对象的属性名,保证不会出现同名的属性。这对于一个对象有多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖。
let mySymbol = Symbol();
/` 第一种写法 */;
let a1 = {};
a1[mySymbol] = 'holle!';
/` 第二种写法 */;
let a2 = {
[mySymbol]: 'holle!'
};
/` 第三种写法 */;
let a3 = {};
Object.defineProperty(a3, mySymbol, { value: 'holle!' });
console.log(a1[mySymbol]); // holle!
console.log(a2[mySymbol]); // holle!
console.log(a3[mySymbol]); // holle!
注意:Symbol 值作为对象的属性名不能使用点运算符,点后面是字符串,不是 Symbol 类型!
Symbol 定义常量
常量使用 Symbol 值的最大的好处就是,其他任何值都不可能有相同的值了。
let log = {};
log.levels = {
DEBUG: Symbol('debug'),
INFO: Symbol('info'),
WARN: Symbol('warn')
};
消除魔术字符串
魔术字符串是指,在代码中多次出现、与代码形成强耦合的某一个具体字符串或数值。风格良好的代码,应该尽量消除魔术字符串,而又含义清晰的变量代替。
/* 字符串Triangle就是一个魔术字符串。它多次出现,与代码形成“强耦合”,不利于将来的修改和维护。 */
function getArea(shape, options) {
let area = 0;
switch (shape) {
case 'Triangle': // 魔术字符串
area = 0.5 * options.width * options.height;
break; /* ... more code ... */
}
return area;
}
getArea('Triangle', {
width: 100,
height: 100
}); // 魔术字符串
常用的消除魔术字符串的方法,就是把它写成一个变量。
我们把 Triangle 写成 shapeType 对象的 triangle 属性,这样就消除了强耦合。
可以发现 shapeType.triangle 等于哪个值并不重要,只要确保不会跟其他 shapeType 属性的值冲突即可。
const shapeType = {
triangle: Symbol('Triangle')
};
function getArea(shape, options) {
let area = 0;
switch (shape) {
case shapeType.triangle:
area = 0.5 * options.width * options.height;
break;
}
return area;
}
getArea(shapeType.triangle, {
width: 100,
height: 100
});
属性名的遍历
Symbol
属性遍历:Object.getOwnPropertySymbols
方法获取指定对象的所有 Symbol
属性。
let keySymbolName = Symbol('name');
let keySymbolAge = Symbol('age');
var a = {
[keySymbolName]: 'houfee',
[keySymbolAge]: 24
};
let arr = Object.getOwnPropertySymbols(a);
console.log(arr); // [Symbol(name), Symbol(age)]
Set 和 Map
Set
Set 本身是一个构造函数,用来生成 Set 数据结构。Set 数据结构类似于数组,但是成员的值都是唯一的,没有重复的值。
const s = new Set();
console.log(typeof s); // object
// 通过add方法向 Set 结构加入成员
[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));
console.log(s); // Set { 2, 3, 5, 4 }
for (let i of s) {
console.log(i);
}
参数
// 接受数组作为参数
const set = new Set([1, 2, 3, 4, 4]);
console.log(set); // [1, 2, 3, 4]
console.log(set.size); // 4
// 接受类似数组的对象作为参数
const set1 = new Set(...document.querySelectorAll('div'));
// 数组去重简单方法:
Array.from(new Set(set));
let arr = [...new Set(set)];
Set 的方法
add(value)
:添加某个值,返回 Set 结构本身。delete(value)
:删除某个值,返回一个布尔值,表示删除是否成功has(value)
:返回一个布尔值,表示该值是否为 Set 的成员clear()
:清除所有成员,没有返回值
使用 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}
WeakSet
WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。
- WeakSet 的成员只能是对象和 Symbol 值,而不能是其他类型的值。
- WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。
WeakSet 结构有以下三个方法。
- WeakSet.prototype.add(value):向 WeakSet 实例添加一个新成员,返回 WeakSet 结构本身。
- WeakSet.prototype.delete(value):清除 WeakSet 实例的指定成员,清除成功返回 true,如果在 WeakSet 中找不到该成员或该成员不是对象,返回 false。
- WeakSet.prototype.has(value):返回一个布尔值,表示某个值是否在 WeakSet 实例之中。
Map
ES6 提供了 Map 数据结构,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。
// 使用对象作为键
const m = new Map();
const o = {
p: 'Hello World'
};
m.set(o, 'holle world!');
m.get(o); // "holle world!"
m.has(o);
m.delete(o);
m.has(o);
Map 也可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。
const map = new Map([
['name', '张三'],
['title', 'Author']
]);
map.size; // 2
map.has('name'); // true
map.get('name'); // "张三"
map.has('title'); // true
map.get('title'); // "Author"
Map 的方法
map.size
map.set(key, value)
map.get(key)
: 读取 key 对应的键值,如果找不到 key,返回 undefinedmap.has(key)
: 返回一个布尔值,表示某个键是否在当前 Map 对象之中map.delete(key)
: 删除某个键,返回 true,如果删除失败,返回 falsemap.clear()
: clear 方法清除所有成员,没有返回值
WeakMap
WeakMap 结构与 Map 结构类似,也是用于生成键值对的集合。
WeakMap 与 Map 的区别有两点。
首先,WeakMap 只接受对象(null 除外)和 Symbol 值作为键名,不接受其他类型的值作为键名。其次,WeakMap 的键名所指向的对象,不计入垃圾回收机制。