美文网首页
ECMAScript6+再整理学习

ECMAScript6+再整理学习

作者: squidbrother | 来源:发表于2021-06-23 16:14 被阅读0次
Ecma国际

Ecma国际自2011年发布国际标准后,到2015年才正式发布新版本 ECMAscript6.0
整体推出都着重解决了哪些问题呢?

  1. 为什么出现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 } //报错 赋值无效
  1. 数组结构与对象结构
    关于数组:
  • 更加优雅的书写变量声明与赋值
    原则,变量可以少,但是多余数据的变量值为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
  1. 函数参数默认值
    没有默认参数的情况下,
function myFn(data){
    data = typeof data === 'undefined' ? 100: data;
    console.log(data)
}

有默认参数的情况下

function myFn(data=100){
    console.log(data)
}
  1. 函数中,不定参的剩余值
function myFn(data,...data2){
    console.log(data); //100
    console.log(data2); // ['aaaa',{name:'zhangsan'}]
}
myFn(100,'aaaa',{name:'zhangsan'})
  1. 箭头函数
  • 箭头函数的出现可以使得函数书写更加简洁
    箭头函数都是匿名函数
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(); 
  1. Obejct.is 能比较出NaN是否等于NaN的特殊比较函数
Object.is(NaN,NaN); //true
Object.is(+0,-0); //false
  1. 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
  1. 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');
  1. 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)]
  1. 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
  1. 数组方法indexOf不能查找NaN
    新增数组方法incloudes
['a',1,2,NaN].includes(NaN); //true
  1. 类的继承与静态方法
  • 通过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();  

未完待续...

相关文章

  • ECMAScript6+再整理学习

    Ecma国际自2011年发布国际标准后,到2015年才正式发布新版本 ECMAscript6.0整体推出都着重解决...

  • ECMAScript6+入门

    let和const ES5有全局作用域和函数作用域,ES6引入块级作用域,前提是必须有大括号,块级作用域不能重复声...

  • 《脱胎换骨的人生整理术》一

    总体来说,这本书讲了整理的两个方面。即,有形物品的整理、无形思维的整理。 先学习有形物品整理,再深入到无形思维的整...

  • 整理,再整理的感受

    换季衣服堆在床上,好多天了。 一直懒得整理。懒得不要不要的。 终于在今天上午,用了差不多两个多小时,整理得差不多了...

  • 整理,再整理的感受

    换季衣服堆在床上,好多天了。 一直懒得整理。懒得不要不要的。 终于在今天上午,用了差不多两个多小时,整理得差不多了...

  • Redis再整理

    什么是 Redis Redis 是用 C 语言开发的一个开源的高性能键值对(key-value)数据库。它通过提供...

  • AsyncTask再整理

    AsyncTask是Android中用于异步处理的辅助类,十分的有用,能够让我们简单的在工作线程中进行耗时操作(比...

  • 整理再思考

    这次整理,大件算是理好了,但还有很多小件没理好。 还有一辆自行车现在客厅呢。 之前是放在北阳台的,现在北阳台全是杂...

  • 【读书清单】怦然心动的人生整理法

    01 我们大多数人其实根本不会整理 整理好的东西很快又乱了,我们不断地陷入整理、变乱、再整理的死循环。 我们该学习...

  • 2019-03-06

    今天还是再整理面试的东西 在学习上没有进度 明天要去杭州和南京

网友评论

      本文标题:ECMAScript6+再整理学习

      本文链接:https://www.haomeiwen.com/subject/xhnhuktx.html