
Ecma国际自2011年发布国际标准后,到2015年才正式发布新版本 ECMAscript6.0
整体推出都着重解决了哪些问题呢?
- 为什么出现let、const
首先是作用域,ES6之前存在 全局作用域、函数作用域,但是并没有块级作用域
- 缺少块级作用域的问题
如果为一组列表元素,添加点击事件,弹出索引值,默认情况下会出现问题,如:
for(var i=0; i<aBtns.length; i++){
aBtns[i].onclick = function(){
console.log(i)
}
}
上述代码,不管点击哪个按钮,其实返回的都是aBtns.length,而非预期的0,1,2,....
这是因为 var 声明的变量是全局的,绑定事件后,其索引i依然累加到aBtns.length了
解决方式:
可以将i做为属性,或者使用函数作用域包裹,如:
var aBtns = document.getElementsByTagName('button');
for(var i=0; i<aBtns.length; i++){
(function(i){
aBtns[i].onclick = function(){
console.log(i)
}
})(i);
}
也可以使用新出现的let的块级作用域
for(let i=0; i<aBtns.length; i++){
aBtns[i].onclick = function(){
console.log(i)
}
}
- 解决早起var的BUG,变量声明提升问题;
如:
console.log(a==undefined); //true
var a = 1;
在不删除var的情况下,推出const、let;
严格的执行 变量'先声明后使用'的原则,否则报错
- 没有声明常量的方式,推出const
值得一提的是,const 针对普通数据类型,不能修改,但是针对引用类型,可以修改属性
const num = 1;
num = 2; //报错 赋值无效
针对引用类型修改属性ok
const student = { name:'', age:0 }
student.name = '张三';
student.age = 18;
console.log(student); //{ name: "张三", age: 18 }
但是针对引用类型数据,直接修改内存地址指向,那么直接报错,因为前后对象内存地址不一样了
如:
const obj = { num:1 }
obj = { num:2 } //报错 赋值无效
- 数组结构与对象结构
关于数组:
- 更加优雅的书写变量声明与赋值
原则,变量可以少,但是多余数据的变量值为undefined
const data = [1,2,3]
let [a,b,c] = data;
console.log(a,b,c) // 1 2 3
- 剩余参数的使用
const data = [1,2,3]
let [a,...b] = data;
console.log(a,b) // 1 [2,3]
- 默认值
const data = [1,2,3]
let [a,b,c,d=4] = data;
console.log(a,b,c,d) // 1 2 3 4
关于对象:
- 对象解构的 别名与默认值 设置
const obj = {name:'zhangsan'}
let {name: objName='default'} = obj;
const name = '123'
console.log(objName); //zhangsan
2-1. 数组与对象中使用展开运算符
优雅的罗列出数组的每一项
const arr = [1,2,3]
console.log(...arr);
在react中,由于底层针对引用数据类型的浅比较,所以不能修改原来的数据引用地址
因此,要返回新的数组或者对象,所以常使用这个展开运算符
如数组 :
const oldData = [1,2,3]
const newData = [ ...oldData, 4,5,6 ]
console.log(newData); // [ 1, 2, 3, 4, 5, 6 ]
如对象(修改值) :
const obj1 = { name:'zhangsan', age:18 }
const obj2 = { ...obj1, age:20 };
console.log(obj2,obj1==obj2); // { name: "zhangsan", age: 20 } false
2-2. 对象的修改,亦可使用Object.assign ,但是第一个参数是谁,结果就是谁的;如果是个空对象,则返回是新对象
const obj1 = { name:'zhangsan', age:18 }
const obj2 = Object.assign(obj1,{name:'lisi'})
console.log(obj2,obj1==obj2); // { name: "lisi", age: 18 } true
返回一个新对象
const obj1 = { name:'zhangsan', age:18 }
const obj2 = Object.assign({},obj1,{name:'lisi'})
console.log(obj2,obj1==obj2); // { name: "lisi", age: 18 } false
- 函数参数默认值
没有默认参数的情况下,
function myFn(data){
data = typeof data === 'undefined' ? 100: data;
console.log(data)
}
有默认参数的情况下
function myFn(data=100){
console.log(data)
}
- 函数中,不定参的剩余值
function myFn(data,...data2){
console.log(data); //100
console.log(data2); // ['aaaa',{name:'zhangsan'}]
}
myFn(100,'aaaa',{name:'zhangsan'})
- 箭头函数
- 箭头函数的出现可以使得函数书写更加简洁
箭头函数都是匿名函数
let addOneFn = num => num+1;
console.log(addOneFn(1)) // 2
- 箭头函数中this的指向问题
this会一直向上找,指向箭头函数定义时所处的对象,而不是箭头函数使用时所在的对象,默认使用父级的this
如果没有箭头函数嵌套的问题存在,默认找到一个没有箭头函数的环境,this是什么就是什么
const obj = {
name:'zhangsan',
sayHi:()=>{
console.log(this); // window
},
sayHiAsync: function(){
console.log(this) // obj
setTimeout(()=>{
console.log(this.name) // zhangsan
console.log(this) // obj
},300)
}
};
obj.sayHi();
obj.sayHiAsync();
- Obejct.is 能比较出NaN是否等于NaN的特殊比较函数
Object.is(NaN,NaN); //true
Object.is(+0,-0); //false
- Proxy 监测对象属性变化
vue3底层中收集依赖的方式,监测数据变化
const data = { name:'zhangsan', age:18 };
const oP = new Proxy(data,{
set(obj,attr,val){
obj[attr] = val;
},
get(obj,attr){
return obj[attr];
}
});
oP.name = 'lisi'
console.log(oP.name); //lisi
- Reflect同proxy类似,同样操作对象相关属性
-
Reflect对象一共有 13 个静态方法。
Reflect.apply(target, thisArg, args)
Reflect.construct(target, args)
Reflect.get(target, name, receiver)
Reflect.set(target, name, value, receiver)
Reflect.defineProperty(target, name, desc)
Reflect.deleteProperty(target, name)
Reflect.has(target, name)
Reflect.ownKeys(target)
Reflect.isExtensible(target)
Reflect.preventExtensions(target)
Reflect.getOwnPropertyDescriptor(target, name)
Reflect.getPrototypeOf(target)
Reflect.setPrototypeOf(target, prototype) -
查看有无属性
// 老写法
'name' in myObj// true
// 新写法
Reflect.has(myObj, 'name') // true
- 获取对象某个属性
Reflect.get(myObj, 'name');
- 获取对象所有属性
Object.keys(myObj);
Reflect.ownKeys(myObj)
- 删除对象属性
// 老写法
delete myObj.name;
//新写法
Reflect.deleteProperty(myObj, 'name');
- symbol
- ES5 的对象属性名都是字符串,这容易造成属性名的冲突
- ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
通过调用一个Symbol函数,就可以获得一个独一无二的属性,防止通过一个对象上挂载属性名冲突
const objName = Symbol();
const obj = {
[objName]:'aaaa',
sayName:function(){
console.log(this[objName])
}
};
obj.sayName();
获取Symbol属性名
const obj = {};
let a = Symbol('a');
let b = Symbol('b');
obj[a] = 'Hello';
obj[b] = 'World';
const objectSymbols = Object.getOwnPropertySymbols(obj);
console.log(objectSymbols) // [Symbol(a), Symbol(b)]
- generator解决异步请求嵌套的问题
- 创建一个生成器函数(通过函数名前加*)
function * fn(){ ... }
- yield关键词,同return可以返回一个结果, 额外的会在此处停止函数执行,通过生成器的next方法,继续后续执行
- yield通过next方法调用的返回值形式为 { value: 'xxx', done: 布尔值 }
- 如果没有yield未执行,或者yield返回值的done值为true时候,整个生成器函数结束
function * say(){
yield 'a';
yield 'b';
yield 'c';
}
const generator1 = say();
let result1 = generator1.next();
let result2 = generator1.next();
let result3 = generator1.next();
let result4 = generator1.next();
console.log(result1,result1.value,result1.done); // {value: "a", done: false} "a" false
console.log(result2.value,result2.done); //b false
console.log(result3.value,result3.done); //c false
console.log(result4.value,result4.done); //undefined true
- 数组方法indexOf不能查找NaN
新增数组方法incloudes
['a',1,2,NaN].includes(NaN); //true
- 类的继承与静态方法
- 通过class 声明, 通过constructor挂载属性,通过super调用父级函数,通过extends继承类
- 函数直接放在类上
- static 是新提供的静态方法,通过类来调用
- proto为实例的原型,prototype为类的原型 ( s1.proto == Student.prototype //true )
class Person {
constructor(name,age) {
this.name = name
this.age = age
}
say(){
console.log(`我叫${this.name},我${this.age}岁`);
}
static createOne(name,age){
return new Person(name,age);
}
}
class Student extends Person {
constructor(name,age,school) {
super(name,age);
this.school = school;
}
myschool(){
console.log(`${this.name}上${this.school}`);
}
static createOne(name,age,school){
return new Student(name,age,school);
}
}
const p1 = Person.createOne('张三',18); //new Person('张三',18);
p1.say();
const s1 = Student.createOne('李四',30,'高中二年级'); //new Student('李四',30,'高中二年级');
s1.say()
s1.myschool();
未完待续...
网友评论