Es6笔记
1.Object.is()
Object.is(a,b);两个值是否相等
var a = 1;
var b = 2;
Object.is(a,b); //false
严格比较运算符(===)的行为基本一致
不同之处只有两个:一是+0不等于-0,二是NaN等于自身
+0 === -0 //true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
2.Object.defineProperty()
Object.defineProperty(obj,prop,descriptor);
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
参数
obj
要定义属性的对象。
prop
要定义或修改的属性的名称或 Symbol 。
descriptor
要定义或修改的属性描述符
var obj = {};
Object.defineProperty(obj,"add",{
value:function(n){
return n+1
},
writable:true
});
var b = obj.add(3);
console.log(b) // 4
3.数值的扩展
1.Number.isFinite()检测数值是否为有限的
2.Number.isNaN() 检测一个值是否为NaN
3.Number.isInterger() 判断一个数值是否为整数
4.Math.trunc()去除一个数的小数部份 返回整数
Math.trunc(4.1) // 4
Math.trunc(4.9) // 4
Math.trunc(-4.1) // -4
Math.trunc(-4.9) // -4
Math.trunc(-0.1234) // -0
Math.trunc('123.456') // 123
Math.trunc(true) //1
Math.trunc(false) // 0
Math.trunc(null) // 0
Math.trunc(NaN); // NaN
Math.trunc('foo'); // NaN
Math.trunc(); // NaN
Math.trunc(undefined) // NaN
5.Math.sign()判断一个数到底是正数/负数/0
Math.sign('') // 0
Math.sign(true) // +1
Math.sign(false) // 0
Math.sign(null) // 0
Math.sign('9') // +1
Math.sign('foo') // NaN
Math.sign() // NaN
Math.sign(undefined) // NaN
6.Bigint 大整数
Bigint后缀需要添加n
const a = 1232343234234234n;
typeof a //bigint
42n === 42 //false
7.指数运算符**
2**2 // 4
2**3 // 8
4**5 // 1024 // 4*4*4*4*4
Math.pow(2,2) // 4
Math.pow(4,5) // 1024 //返回 4 的 5 次幂
4.函数的扩展
1.函数参数设置默认值
function log(x,y = ''world'){
console.log(x,y)
}
log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello
2.函数rest参数 (形式为…变量名)
function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
add(2, 5, 3) // 10
rest参数后不能再有其他参数
3.箭头函数 =>
1.
var f = v=>v;
//等同于
var f = function(v){
returnt v;
}
2.
var f = ()=> 5;
//等同于
var f = function(){ return 5 };
3.
(n)=>{return n}
//等同于
function(n){return n}
5.数组的扩展
1.扩展运算符 三个点(…) 将一个数组转为用逗号分隔的参数序列
var a = [1,2,3];
var b = [4,5,6];
function pus(array,...items){
array.push(...items)
return array;
}
pus(a,...b); //[1, 2, 3, 4, 5, 6]
console.log(...[1,2,3,4,5]) // 1 2 3 4 5
1.复制数组
const a1 = [1, 2];
// 写法一
const a2 = [...a1];
// 写法二
const [...a2] = a1;
2.合并数组
const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];
// ES5 的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]
// ES6 的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]
3.将字符串转为数组
[...'hello'] //[ "h", "e", "l", "l", "o" ]
2.Array.from() 将两类对象转为真正的数组
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
3.Array.of() 将一组值转换为数组
Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1
4.Array.find() 和 findIndex()
数组实例的find
方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出***第一个***返回值为true
的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined
。
var list = [
{id:1,name:'dddd1'},
{id:2,name:'dddd2'},
{id:3,name:'dddd3'},
{id:4,name:'dddd4'},
];
list.find((item)=>{return item.id ===2 } )
// {id: 2, name: "dddd2"}
find方法的回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组。
[1, 5, 10, 15].find(function(value, index, arr) {
return value > 9;
})
// 10
findIndex() 方法的用法与 find() 方法非常类似 区别是 findIndex()没有找到 返回 -1;
两个方法都可以接受第二个参数,用来绑定回调函数的this
对象。
function f(v){
return v > this.age;
}
let person = {name: 'John', age: 20};
[10, 12, 26, 15].find(f, person);
// 26
5.fill()
fill
方法使用给定值,填充一个数组。
['a', 'b', 'c'].fill(7)
// [7, 7, 7]
new Array(3).fill(7)
// [7, 7, 7]
fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。
['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']
fill方法从 1 号位开始,向原数组填充 7,到 2 号位之前结束
注意,如果填充的类型为对象,那么被赋值的是同一个内存地址的对象,而不是深拷贝对象。
let arr = new Array(3).fill({name: "Mike"});
arr[0].name = "Ben";
arr
// [{name: "Ben"}, {name: "Ben"}, {name: "Ben"}]
let arr = new Array(3).fill([]);
arr[0].push(5);
arr
// [[5], [5], [5]]
6.entries()、keys() 、values()
entries()是对键值对的遍历
keys() 是对键名的遍历
values()
是对键值的遍历
var arr = ["a","b","c","d"];
for(let index of arr.keys()){
console.log(index)
}
// 0 1 2 3
var arr = ["a","b","c","d"];
for(let index of arr.values()){
console.log(index)
}
// a b c d
let letter = ['a', 'b', 'c'];
let entries = letter.entries();
console.log(entries.next().value); // [0, 'a']
console.log(entries.next().value); // [1, 'b']
console.log(entries.next().value); // [2, 'c']
7.includes() 查找某个数组是否包含指定值 返回布尔值
['a','b','c'].includes('a');
// true
该方法的第二个参数表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为-4,但数组长度为3),则会重置为从0开始。
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
8.filter(); 对数组进行过滤
filter()语法 var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])
参数
-
callback
用来测试数组的每个元素的函数。返回
true
表示该元素通过测试,保留该元素,false
则不保留。它接受以下三个参数:element
数组中当前正在处理的元素。index
可选正在处理的元素在数组中的索引。array
可选调用了filter
的数组本身。 -
thisArg
可选执行
callback
时,用于this
的值。一个新的、由通过测试的元素组成的数组,如果没有任何数组元素通过测试,则返回空数组。
如果数组里面的元素是对象 只是浅拷贝
var list1 = [ {id:1,name:'aa'}, {id:2,name:'bb'}, {id:3,name:'cc'}, {id:4,name:'dd'} ]; var arr = list1.filter(function(a,index,array){return index===2}); console.log(arr) // [{id:4,name:'dd'}]
var list = [5,6,9,3,1,5,8,7,4,2,6,9];
var b = list.filter(n=>{return n>5})
//注意函数写法
1.(a)=>{return a>0}
2.a=>a>0
3.(a)=>a>0
4.function(a){return a>0}
console.log(b) // [6, 9, 8, 7, 6, 9]
var list1 = [
{id:1,name:'aa'},
{id:2,name:'bb'},
{id:3,name:'cc'},
{id:4,name:'dd'}
];
var arr = list1.filter(item=>item.id>2);
console.log(arr) //[{id:3,name:'cc'},{id:4,name:'dd'}]
9.map()
var b = a.map(item=>{return fn(item)})
**map()**
方法创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值
语法
var new_array = arr.map(function callback(currentValue[, index[, array]]) {
// Return element for new_array
}[, thisArg])
参数
-
callback
生成新数组元素的函数,使用三个参数:
currentValue``callback
数组中正在处理的当前元素。index
可选callback
数组中正在处理的当前元素的索引。array
可选map
方法调用的数组。 -
thisArg
可选执行
callback
函数时值被用作this
。
返回值
一个由原数组每个元素执行回调函数的结果组成的新数组。
var list = [
{id:1,name:'aa',age:15},
{id:2,name:'bb',age:16},
{id:3,name:'cc',age:18},
{id:4,name:'dd',age:10}
];
function add(n){
n.age += 2;
return n;
}
var arr = list.map((a)=>{return add(a)}); //可以简写成 var arr = list.map(add);
console.log(arr)
// [
{id:1,name:'aa',age:17},
{id:2,name:'bb',age:18},
{id:3,name:'cc',age:20},
{id:4,name:'dd',age:12}
]
10.js5 数组常用方法
var arr = [‘a’,‘b’,‘c’];
10-1、toString(); 将数组转为字符串(逗号分隔)
var a = arr.toString(); //a,b,c
10-2、join();将数组元素结合为一个字符串(可以自己定义分隔符)
var a = arr.join(); // a,b,c
var b = arr.join(’’); //abc
var c = arr.join(’*’); //a*b*c
10-3、pop 删除最后一个元素
var a = arr.pop() // c
console.log(arr) //[a,b]
10-4、push 结尾处添加
arr.push(‘d’);// [a,b,c,d]
10-5、shift 删除首个元素
arr.shift() ; //[b,c]
10-6、unshift 数组开头添加新元素
arr.unshift(‘aa’); //[aa,a,b,c]
10-7、splice() ; 数组增删改
arr.splice(1) ; // 一个参数,删除 从1到最后一个 //[ a ]
arr.splice(1,1) //第一个参数表示数组下标 第二个参数表示要删除的个数 // [ a,c ]
arr.splice(1,2,‘aa’,‘bb’);//从下标1位置删除两个元素 并在1位置开始插入 aa bb的数据,数据可以定义多个
10-8、concat();合并数组
var b = [‘d’,‘e’,‘f’];
var c = a.concat(b);
console.log©; // [ a,b,c,d,e,f] //不会改变原数组
6.对象的扩展
1.链判断运算符 ?.
有时候需要将一个对象中的变量赋值给一个变量
var name = message.body.user.name;
但是当body 或者 user 不存在时 回报错
可以这样写
var name = (message && message.body && message.body.user && message.bodu.user.name) || "default"
或者用三目写
但是有了链判断运算符就不同了
var name = message?.body?.user?.name;
链式调用的时候判断,左侧的对象是否为null或undefined。如果是的,就不再往下运算,而是返回undefined。
7.Symbol 第七种数据类型 表示独一无二的值
前六种是:undefined
、null
、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)
Symbol
函数前不能使用new
命令,否则会报错。
由于 Symbol 值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型
凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突
let s1 = Symbol();
s1 = "123abc";
console.log(s1) // 123abc
Symbol函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分
let s1 = Symbol('foo');
let s2 = Symbol('bar');
s1; // Symbol(foo)
s2; // Symbol(bar)
Symbol 属性 desctiption 返回Symbol的描述
const sym = Symnol('foo');
sym.description; //'foo'
8.Set 数据结构
1.类似于数组 成员值都是唯一的 没有重复的值
const s = new Set();
[2,3,4,5,6,4,6,5,2,2].forEach(x=>s.add(x));
console.log(s) // 2,3,4,5,6
var list= [1,2,5,8,9,4,3,2,5,8,4,1];
[...new Set(list)] //[1,2,5,8,9,4,3] //数组去重
[...new Set('abba')].join('') // ab 去除字符串里面的重复字符
var a = NaN;
var b = NaN;
console.log(a===b); //false ===认为NaN不等于自身
var s = new Set();
s.add(a);
s.add(b);
console.log(s) //Set{NaN} set加入值时认为NaN等于自身
如果是两个对象 === 认为是不相等的 set视为两个值 会添加两次
2.Set 结构的实例有的属性
1.Set.prototype.constructor 构造函数 默认就是set函数
2.Set.prototype.size 返回set实例的成员总数
3.Set实例的方法 :操作方法
1.Set.prototype.add(value) 添加某个值,返回Set结构本身
2.Set.prototype.delete(value) 删除某个值返回一个Boolean 表示删除是否成功
3.Set.prototype.has(value) 返回一个布尔值 表示set是否有该值
4.Set.prototype.clear();清除所有成员,没有返回值
//实例
let s = new Set();
s.add(1).add(2).add(2);
s.size; //2
s.has(1); //true
s.has(2); //true
s.has(3); //false
s.delete(2);
s.has(2); //false
4.Setb遍历方法
Set.prototype.keys():返回键名的遍历器
Set.prototype.values():返回键值的遍历器
Set.prototype.entries():返回键值对的遍历器
Set.prototype.forEach():使用回调函数遍历每个成员
5.Array.from() 方法可以将Set机构转为数组
let s=new Set();
s.add(1).add(2).add(3);
let a = Array.from(s);
console.log(a) // [1,2,3]
[...s] 也可以转为数组
数组去重的另一种方法
function dedupe(array){
return Array.from(new Set(array));
}
dedupe([1,2,4,5,7,3,1,2]) ; //[1,2,4,5,7,3]
9.Map 数据结构
Map数据结构 类似于对象,也是键值对的集合。
那为什么有了对象还增加Map呢?
因为 对象 的键只能用字符串,而Map的键不限于字符串,各种类型都可以当作键(包括对象)
const m = new Map();
const o = {p: 'Hello World'};
m.set(o, 'content')
m.get(o) // "content"
m.has(o) // true
m.delete(o) // true
m.has(o) // false
上面代码使用 Map 结构的set方法,将对象o当作m的一个键,然后又使用get方法读取这个键,接着使用delete方法删除了这个键。
Map 属性和操作方法:
1.size 属性 返回Map结构的成员总数 map.size
2.set(key,value) ;set 方法设置键名key对应的键值为value
3.get(key) get方法读取key对应的键值
4.has(key) has方法返回一个布尔值
5.delete(key) 删除某个键
6.clear() 清除所有成员
遍历方法
Map 结构原生提供三个遍历器生成函数和一个遍历方法。
Map.prototype.keys():返回键名的遍历器。
Map.prototype.values():返回键值的遍历器。
Map.prototype.entries():返回所有成员的遍历器。
Map.prototype.forEach():遍历 Map 的所有成员。
const map = new Map([
['F', 'no'],
['T', 'yes'],
]);
for (let key of map.keys()) {
console.log(key);
}
// "F"
// "T"
for (let value of map.values()) {
console.log(value);
}
// "no"
// "yes"
for (let item of map.entries()) {
console.log(item[0], item[1]);
}
// "F" "no"
// "T" "yes"
// 或者
for (let [key, value] of map.entries()) {
console.log(key, value);
}
// "F" "no"
// "T" "yes"
// 等同于使用map.entries()
for (let [key, value] of map) {
console.log(key, value);
}
// "F" "no"
// "T" "yes"
Map转数组
最常用是使用扩展运算符 ( …)
const myMap = new Map()
.set(true, 7)
.set({foo: 3}, ['abc']);
[...myMap]
// [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]
10.Class
类不存在变量提升 (声明提前)
1.基本语法
class Point{
constructor(x,y){ // 构造方法
this.x = x;
this.y = y;
}
toString(){
console.log(this.x+this.y);
}
}
var point1 = new Point('a','b');
point1.toString(); // ab
typeof Point // 'function'
Point === Point.prototype.constructor // true
2.注意事项
class Point{
}
//等同于
class Point{
constructor(){}
}
一个类必须有constructor方法,没有定义 会默认添加一个空的constructor方法
let Point1 = new Point(); // 必须使用new调用 否则会报错
3. 类的方法
class Point{
constructor(x,y){
this.x = x;
this.y = y;
}
toString(){
//...
}
toValue(){
//...
}
}
//等同于
Point.prototype = {
constructor(x,y){this.x = x;this.y = y;},
toString(){},
toValue(){}
}
类的所有方法都定义在类的prototype属性上面
Point.prototype.constructor === Point // true
let point1 = new Point();
point.hasOwnProperty("x") //true
point.hasOwnProperty("y") //true
point.hasOwnProperty("toString") //false
point.__proto__.hasOwnProperty("toString") //true
通过Object.assign方法添加多个方法
class Point{
constructor(){ //... }
}
Object.assign(Point.prototype,{
toString(){},
toValue(){}
})
类的内部所有定义的方法 都是不可枚举的
Object.keys(Point.prototype);
// []
Object.getOwnPropertyNames(Point.prototype)
// ["constructor","toString","toValue"]
4.getter 和 setter
class MyClass{
constructor(){
//...
}
get prop(){
return'getter';
}
set prop(value){
console.log('setter:'+value);
}
}
let inst = new MyClass();
inst.prop = 123;
//setter:123
inst.prop
//'getter'
prop属性有对应的存值函数和取值函数,因此赋值和读取行为都被自定义了。
5.类的静态方法 static
class Foo{
static bar(){ //方法前有static关键字 表明是一个静态方法
this.baz()
}
static baz(){
console.log('hello')
}
baz(){
console.log('world')
}
}
Foo.bar(); //hello
静态方法 不会被实例继承
静态方法 直接使用类调用,而不是在类的实例上调用;
静态方法中的this 指的是类 而不是实例
静态方法可以与非静态方法重名
父类的静态方法 可以被子类继承
6.继承
父类的静态方法 可以被子类继承
class Foo{ //父类
static classMethod(){
return 'hello'
}
}
class Bar extends Foo{ //Bar 继承 Foo(父类) 的静态方法
}
Bar.classMethod() //'hello'
11.js 常用方法
1.防抖 debounce
触发高频时间后n秒内函数只会执行一次,如果n秒内高频时间再次触发,则重新计算时间
const debounce = (fn,time)=>{
let timeout = null;
return function(){
clearTimeout(timeout);
timeout = setTimeout(()=>{
fn.apply(this,arguments);
},time)
}
}
//‘getter’
prop属性有对应的存值函数和取值函数,因此赋值和读取行为都被自定义了。
##### 5.类的静态方法 static
class Foo{
static bar(){ //方法前有static关键字 表明是一个静态方法
this.baz()
}
static baz(){
console.log(‘hello’)
}
baz(){
console.log(‘world’)
}
}
Foo.bar(); //hello
静态方法 不会被实例继承
静态方法 直接使用类调用,而不是在类的实例上调用;
静态方法中的this 指的是类 而不是实例
静态方法可以与非静态方法重名
父类的静态方法 可以被子类继承
##### 6.继承
父类的静态方法 可以被子类继承
class Foo{ //父类
static classMethod(){
return ‘hello’
}
}
class Bar extends Foo{ //Bar 继承 Foo(父类) 的静态方法
}
Bar.classMethod() //‘hello’
## 11.js 常用方法
#### 1.防抖 debounce
触发高频时间后n秒内函数只会执行一次,如果n秒内高频时间再次触发,则重新计算时间
const debounce = (fn,time)=>{
let timeout = null;
return function(){
clearTimeout(timeout);
timeout = setTimeout(()=>{
fn.apply(this,arguments);
},time)
}
}