最近开始重学前端,学习过程中将笔记跟大家分享,希望对大家有所帮助,共同成长,文章中有不对的地方请大家指正。
本文简单列举了ES6+中的一些新特性,部分知识点涉及面过大,本文将一带而过,后面将会另起一篇去做详细介绍,比如:Promise,Generator等。
//块级作用域一级块级作用域的使用
if(true) {
const param = 'param in if block';
console.log(param);//param in if block
}
console.log(param);//块级作用域外访问内部定义的变量,ReferenceError: param is not defined
// 暂时性死区
const i = 100;
if(i) {
console.log(i); //ReferenceError: Cannot access 'i' before initialization
const i = 1000;
}
// const常量声明必须初始化
const i;
i = 10;
console.log(i) //SyntaxError: Missing initializer in const declaration
// 基本类型常量不能修改,引用类型常量能修改属性
const str = 'str';
str = 'str1';//TypeError: Assignment to constant variable.
const arr = [1, 2, 3];
arr[0] = 100;
console.log(arr[0]) //100
声明方式 | 变量提升 | 作用域 | 初始值 | 重复定义 |
---|---|---|---|---|
var | 是 | 函数级 | 不需要 | 允许 |
let | 否 | 块级 | 不需要 | 不允许 |
const | 否 | 块级 | 必需 | 不允许 |
const arr = [1, 2, 3];
const [a, b, c] = arr;
console.log(a, b, c);//1,2,3
const [, , d] = arr;
console.log(d)//3
const arr = [1, 2, 3];
const [, , , defaultVal = '4'] = arr;
console.log('设置默认值',defaultVal);
const arr = [1, 2, 3];
const [e, ...rest] = arr;
console.log(rest)//[2, 3]
// 拆分字符串
const str = 'xiaobai/18/200';
const strArr = str.split('/');
const [, age, ] = strArr;
console.log(age)//18
const obj = {name: 'xiaohui', age: 18, height: undefined};
const {name, age} = obj;
console.log(name, age) // 'xiaohui', 18
const obj = {name: 'xiaohui', age: 18, height: undefined};
const {mame: objMame} = obj;
console.log(objMame)
const obj = {name: 'xiaohui', age: 18, height: undefined};
const {mame: objMame} = obj;
console.log(objMame)
//换行
const str = `fdsjak
fdsa`
console.log(str)
// 插值
const strs = `random: ${Math.random()}`;
console.log(strs)
/**
* 字符串模板函数
* @param {array} strs 以插值为分隔符组成的字符串数组
* @param {string} name 插值的value,有多少个就会传入多少个
*/
const tagFunc = (strs, name, gender) => {
const [str1, str2, str3] = strs;
const genderParsed = gender == "1" ? "男" : "女";
// 可以在此做过滤,字符串处理,多语言等操作
return str1 + name + str2 + str3 + genderParsed;
};
// 带标签的模板字符串,
const person = {
name: "xiaohui",
gender: 1,
};
// 返回值为标签函数的返回值
const result = tagFunc`my name is ${person.name}.gender is ${person.gender}`;
console.log(result);//my name is xiaohui.gender is 男
const str = 'abcd';
console.log(str.includes('e'));//false
console.log(str.startsWith('a'));//true
console.log(str.endsWith('a'))//false
// 带默认参数的形参一般放在后面,减少传参导致的错误几率
const defaultParams = function (name,age = 0) {
return [age, name]
};
console.log(defaultParams(1))
// 剩余参数,转化成数组
const restParams = function(...args) {
console.log(args.toString());//1, 2, 3, 4, 5
}
restParams(1, 2, 3, 4, 5)
使用...将数组展开
const arr = [1, 2, 3];
console.log(...arr);
// 等价于es5中以下写法
console.log.apply(console, arr)
特性&优势:
const inc = n => n + 1;
console.log(inc(100))
const obj = {
name: 'aa',
func() {
setTimeout(() => {
console.log(this.name);//aa
}, 0);
setTimeout(function() {
console.log(this.name);//undefined
}, 0);
}
}
obj.func();
/**
* 1、增强了对象字面量:
* 1,同名属性可以省略key:value形式,直接key,
* 2,函数可以省略key:value形式
* 3,可以直接func(),
* 4,可以使用计算属性,比如:{[Math.random()]: value}
*/
const arr = [1, 2, 3];
const obj = {
arr,
func(){console.log(this.arr)},
[Math.random()]: arr
}
console.log(obj)
/**
* Object.assign(target1, target2, ...targetn)
* 后面的属性向前面的属性合并
* 如果target1是空对象,可以创建一个全新对象,而不是对象引用
*/
const obj1 = {
a: 1,
b: 2
};
const obj2 = {
a: 1,
b: 2,
};
const obj3 = Object.assign({}, obj1);
obj3.a = 5;
console.log(obj3, obj2, obj1);
作用:
比较两个值是否相等
特性:
console.log(NaN === NaN) //false
console.log(Object.is(NaN, NaN)) //true
console.log(0 === -0) // true
console.log(Object.is(0, -0))//false
console.log(Object.is(1, 1))//true
作用:
用法:
const P = {
n: "p",
a: 19,
};
const proxy = new Proxy(P, {
get(target, property) {
console.log(target, property);
return property in target ? target[property] : null;
},
defineProperty(target, property, attrs) {
console.log(target, property, attrs);
// throw new Error('不允许修改')
},
deleteProperty(target, property) {
console.log(target, property);
delete target[property];
},
set(target, property, value) {
target[property] = value;
},
});
proxy.c = 100;
console.log('pp',P);
与Object.definePropert对比
优势:
拥有很多defineProperty没有的属性方法,比如:
handler.getPrototypeOf() ---Object.getPrototypeOf 方法的监听器
handler.setPrototypeOf() ---Object.setPrototypeOf 方法的监听器。
handler.isExtensible() ---Object.isExtensible 方法的监听器。
handler.preventExtensions() ---Object.preventExtensions 方法的监听器。
handler.getOwnPropertyDescriptor() ---Object.getOwnPropertyDescriptor 方法的监听器。
handler.defineProperty() ---Object.defineProperty 方法的监听器。
handler.has() ---in 操作符的监听器。
handler.get() ---属性读取操作的监听器。
handler.set() ---属性设置操作的监听器。
handler.deleteProperty() ---delete 操作符的监听器
handler.ownKeys() ---Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的监听器。
handler.apply() ---函数调用操作的监听器。
handler.construct() ---new 操作符的监听器。
对数组的监视更方便
以非侵入的访视监管对象的读写
作用:
集成Object操作的所有方法,统一、方便,具体方法如下:
用于对对象的统一操作,集成Object相关的所有方法
1、apply:类似Function.prototype.apply
2、Reflect.construct()
对构造函数进行 new 操作,相当于执行 new target(...args)。
3、Reflect.defineProperty()
和 Object.defineProperty() 类似。
4、Reflect.deleteProperty()
作为函数的delete操作符,相当于执行 delete target[name]。
5、Reflect.get()
获取对象身上某个属性的值,类似于 target[name]。
6、Reflect.getOwnPropertyDescriptor()
类似于 Object.getOwnPropertyDescriptor()。
7、Reflect.getPrototypeOf()
类似于 Object.getPrototypeOf(), 获取目标对象的原型。
8、Reflect.has()
判断一个对象是否存在某个属性,和 in 运算符 的功能完全相同。
9、Reflect.isExtensible()
类似于 Object.isExtensible().判断对象是否可扩展,可以添加额外属性
Object.seal(封闭对象), Object.freeze(冻结对象)是不可扩展的
10、Reflect.ownKeys()
返回一个包含所有自身属性(不包含继承属性)的数组。(类似于 Object.keys(), 但不会受enumerable影响).
11、Reflect.preventExtensions()
类似于 Object.preventExtensions()。返回一个Boolean。
12、Reflect.set()
将值分配给属性的函数。返回一个Boolean,如果更新成功,则返回true, 反之返回false。
13、Reflect.setPrototypeOf()
类似于 Object.setPrototypeOf()。
示例:
const obj = {
name: 'reflect'
}
Reflect.preventExtensions(obj);//禁止扩展
console.log(Reflect.set(obj, 'age', 'xiaobai'))//false
console.log(obj)//{ name: 'reflect' }
console.log(Reflect.isExtensible(obj, 'name'))//false
console.log(Reflect.ownKeys(obj))//[ 'name' ]
作用:解决异步编程中回调嵌套过深问题
class Person{
constructor(props) {
this.props = props;
}
}
class Person{
constructor(props) {
this.props = props;
}
// 实例方法
eat() {
}
// 静态方法
static run() {
}
}
// 调用静态方法
Person.run();
const person = new Person('props');
// 调用实例方法
person.eat();
class Student extends Person {
constructor(props) {
super(props);
}
printProps() {
console.log(this.props);
}
}
const student = new Student('student');
student.printProps();
说明:
Set是一种类似于数组的数据结构
特性:
用途:
const arr = [1,3,1,1,1]
const set = new Set(arr);
set.add(1).add(1);
console.log(set.size)//2
const newArr = Array.from(set);
console.log(newArr)//[ 1, 3 ]
说明:
类似Object,以key、value形式存储数据
区别:
Map键不会隐式转换成字符串,而是保持原有类型
实例:
const map = new Map();
map.set(1, 1);
map.set('name', 'map')
map.set(obj, obj)
console.log(map.get(1)) //1
/**
1 1
name map
{ '1': 1, true: true, a: 'a' } { '1': 1, true: true, a: 'a' }
*/
map.forEach((val, key) => {console.log(key, val)})
说明:
JavaScript第六种原始数据类型,用来定义一个唯一的变量
// 对象属性重名问题;
const objSymbol = {
[Symbol()]: 1,
[Symbol()]: 2
}
console.log(objSymbol)
// 2、为对象、类、函数等创建私有属性
const name = Symbol();
const obj2 = {
[name]: 'symbol',
testPrivate() {
console.log(this[name]);
}
}
obj2.testPrivate();
// 定义toString标签;
console.log(obj2.toString());
obj2[Symbol.toStringTag] = 'xx';
console.log(obj2.toString());//[object xx]
用途:
已统一的方式,遍历所有引用数据类型
特性:
可以随时使用break终止遍历,而forEach不行
实例:
// 基本用法
// 遍历数组
const arr = [1, 2, 3, 4];
for(const item of arr) {
if(item > 3) {
break;
}
if(item > 2) {
console.log(item)
}
}
// 遍历set
const set = new Set();
set.add('foo').add('bar');
for(const item of set) {
console.log('set for of',item)
}
// 遍历map
const map = new Map();
map.set('foo', 'one').set('bar', 'two');
for(const [key, val] of map) {
console.log('for of map',key, val)
}
//迭代对象
const obj = {
name: "xiaohui",
age: "10",
store: [1, 2, 3],
// 实现可迭代的接口
[Symbol.iterator]: function () {
const params = [this.name, this.age, this.store]
let index = 0;
return {
next() {
const ret = {
value: params[index],
done: index >= params.length,
};
index++;
return ret;
},
};
},
};
for (const item of obj) {
console.log("obj for of", item);
}
/**
* 迭代器模式* 作用:通过Symbol.interator对外提供统一的接口,获取内部的数据
* 外部可以通过for...of...去迭代内部的数据*/
const tods = {
life: ["eat", "sleep"],
learn: ["js", "dart"],
// 增加的任务
work: ["sale", "customer"],
[Symbol.iterator]: function () {
const all = [];
Object.keys(this).forEach(key => {
all.push(...this[key])
})
let index = 0;
return {
next() {
const ret = {
value: all[index],
done: index >= all.length,
};
index++;
return ret;
},
};
},
};
for (const item of tods) {
console.log(item);
}
// 生成迭代器方法
// 生成器Generator的应用
function* createIdGenerator() {
let id = 1;
while (id<3) yield id++;
}
const createId = createIdGenerator();
console.log(createId.next());//{ value: 1, done: false }
console.log(createId.next());//{ value: 2, done: false }
console.log(createId.next());//{ value: undefined, done: true }
const todos = {
life: ["eat", "sleep", "baba"],
learn: ["es5", "es6", "design pattern"],
work: ["b", "c", "framework"],
[Symbol.iterator]: function* () {
const all = [...this.life, ...this.learn, ...this.work];
for(const i of all) {
yield i;
}
},
};
for(const item of todos) {
console.log(item)
}
判断数组是否包含某个元素,包含NaN,解决indexOf无法查找NaN问题
// includes函数
const arr = ["foo", "bar", "baz", NaN];
console.log(arr.includes(NaN));//true
console.log(arr.indexOf(NaN));//-1
指数运算
// 指数运算符 **
// es5中2十次方
console.log(Math.pow(2, 10));
// es6中2十次方
console.log(2 ** 10);
将对象的值以数组的形式返回
const obj = {
foo: 1,
bar: 2,
baz: 3,
};
console.log(Object.values(obj));//[ 1, 2, 3 ]
将对象以键值对二维数组返回,使之可以使用for...of...遍历
const obj = {
foo: 1,
bar: 2,
baz: 3,
};
console.log(Object.entries(obj));
const entry = Object.entries(obj);
for (const [key, value] of entry) {
console.log(key, value);
}
获取对象的描述信息
可以通过获得的描述信息,配合Object.defineProperties来完整复制对象,包含get,set方法
// getOwnPropertyDescriptors
// 普通get方法
const objGet = {
foo: 1,
bar: 2,
get getCount() {
return this.foo + this.bar;
},
};
// assign方法会把getCount当做普通属性复制,从而getCount为3,修改bar不管用
const objGet1 = Object.assign({}, objGet);
objGet1.bar = 3;
console.log(objGet1.getCount);//3
// descriptors
const descriptors = Object.getOwnPropertyDescriptors(objGet);
console.log("des", descriptors);
// 通过descriptors来复制对象,可以完整复制对象,包含get,set
const objGet2 = Object.defineProperties({}, descriptors);
objGet2.bar = 3;
console.log(objGet2.getCount);//4
在字符串前,或者后面追加指定字符串
参数:
targetLenght: 填充后的目标长度
padString:填充的字符串
规则:
1、填充的字符串超过目标长度,会在规定长度时被截断
2、填充字符串太短会以空格填充
3、padString未传值,以空格填充
作用:
一般用来对齐字符串输出
/**
* foo.................|1
barbar..............|2
bazbazbaz...........|3
*/
console.log(`${key.padEnd(20, '.')}${value.toString().padStart(2, '|')}`)
出处:https://juejin.cn/post/6863266417194565645