es6学习笔记二-对象新增API与类

对象

新增的对象字面量语法

  1. 成员速写
    如果对象字面量初始化时,成员的名称来自一个变量,并且和变量名称相同,则可以进行简写
function obj (name,age){
    let sayHello = function(){
        console.log(this.name,this.age);
    }
    return {
        naem,//成员名称与变量相同可简写
        age,
        sayHello,//函数也一样
    }
}

obj("java","script");
  1. 方法速写
    对象字面初始化时,方法可以省略冒号和function关键字
let obj = {
    name:"java",
    age:"script",
    //下面写法与 fn:function(){  console.log(this.name,this.age);}无区别,只是更方便
    fn(){
        console.log(this.name,this.age);
    }
}
  1. 计算属性名
    有的时候,初始化对象时,某些属性名可能来自于某个表达式的值,在es6,可以使用中括号来表示该属性名是通过计算得到的
let a = "name";
let b = "age";
let c ="sayHello";
let obj = {};
//想要上面的变量的值,表示对象obj中的属性名,es6前做法  
obj[a]="java";
obj[b]= "script"
obj[c]=function(){};
//es6:可以直接在对象中用[]来表示   
obj= {
    [a]:"java",
    [b]:"script",
    [c]:function(){}
}

Object的新增API

  1. Object.is
    用来判断两个数据是否相等,基本上跟严格相等(===)是一致的,除了以下两个点:

console.log(NaN===NaN);//false  明明两个一样的却不相等
console.log(+0===-0);//true +0,-0计算机存储的二进制不同,却相等  

//Object.is就是为了解决这两个问题新增的  
console.log(Object.is(NaN,NaN));//true
console.log(Object.is(+0,-0));//fales
  1. Object.assign
    用过合并对象
let obj1 ={a:1,b:2};
let obj2 ={a:2,b:2,c:4};
//相同于浅克隆
let obj3= Object.assign(obj1,obj2);//obj2合并到obj1中,然后返回obj1
console.log(obj1 == obj3);//true

//另外还可以用es7的...  
let obj4 ={
    ...obj1,
    ...obj2
}
  1. Object.getOwnPropertyNames的枚举顺序
    Objec.getOwnPropertyNames方法之前就存在,只不过,官方没有明确要求,对属性的顺序如何排序,完全由浏览器厂商决定
    es6规定了该方法返回的数组的排列方式如下:
  • 先排数字,并按照升序顺序
  • 再排其他
  1. Object.setPrototypeOf
    该函数用于设置某个对象的隐式原型
let a={a:1};
let b ={b:2};

//obj1.__proto__=obj2  
Object.setPrototypeOf(obj1,obj2);

类:构造函数

传统的构造函数的问题

  1. 属性和原型方法定义分离,降低了可读性
function Person(name,age){
    this.name = name;
    this.age = age;
}
//如果代码量多,总是XX.prototype.XX下去,会造成不易阅读
Person.prototype.show = function(){}

  1. 原型成员可以被枚举
function Person(name,age){
    this.name = name;
    this.age = age;
}
//如果代码量多,总是XX.prototype.XX下去,会造成不易阅读
Person.prototype.show = function(){}

let pr = new Person();
for(let prop in pr ){
    console.log(prop);
}
  1. 默认情况下,构造函数仍然可以被当作普通函数使用

类的特点

  1. 类声明不会被提升,与let和const一样,存在暂时性死区
  2. 类中的所有代码均在严格模式执行
  3. 类的所有方法都是不可枚举的
  4. 类的所有方法都是无法被当作构造函数使用
  5. 类的构造器必须使用new来调用
class Person {
    constructer(name,age){//相当于es5中的构造函数 
        this.name = name;
        this.age = age;
    }

    show(){

    }
}  

let pr = new Person("java","script");

let sh =new  pr.show(); //类的所有方法都是无法被当作构造函数使用  

for(let prop in person){
    console.log(prop);//不会遍历原型上的方法
}

console.log(wid)

类的其他书写方式

  1. 可计算的成员名
let methedName  = "show"; 
class Person {
    constructer(name,age){ 
        this.name = name;
        this.age = age;
    }

    [methedName](){

    }
}  
  1. getter和setter
    es5中Object.defineProperty可定义某个对象成员属性的读取与设置
class Person {
    constructer(name,age){ 
        this.name = name;
        this.age = age;//直接赋值就可以,下面方法会运行

        //如果作es5的Object.defineProperty
        //参数分别为对象,属性名,配制属性
        Object.defineProperty(this,"age",{
            set(val){},
            get(){}
        })
    }
    //创建一个age属性,并给它加上getter,读取该属性时,会运行该函数
    get age (){//没有参数
        return this.age +"岁";
    }

    //创建一个age属性时,并给它加上setter,给该属性赋值时,会运行该函数
    set age(age){//参数
        if(age<0){
            age = 0;
        }
        else if(age>1000){
            age = 1000;
        }
    }
    show(){

    }
}  
  1. 静态成员
    静态成员是在构造函数本身上的成员
    使用static关键字定义的成员即静态成员
    每次new创建对象时都会占内存
class Person {
    constructer(name,age){ 
        this.name = name;
        this.age = age;
    }
    static sex = "男";
    static weight = 120;
    static mehtod(){}

   show(){

    }
}  

console.dir(Person);
//取静态成员  
Person.medthod();
Person.sex  
person.weight;
  1. 字段初始化器(es7)
class Text(){
    a = 1;//相同于在constructer构造函数中的this.a
   constructer(){
       //this.a = 1;//实例成员是固定值,可以换一种写法,直接在constructer外写
   }
}

注意:

  • 使用static的字段初始化器,添加的是静态成员
  • 没有使用static的字段初始化器,添加的成员位于实例对象上
  • 箭头函数在字段初始化器位置上,指向当前对象
class Text(){
    method = ()=>{};
    //上面这种写法相同于
    constructer(){
        this.method = ()=>{}//this指向的是Text对象
    }
}
  1. 类表达式
    装饰器的本质是一个函数
const obj = class {//匿名类
    a = 1;
    b = 2;
}
  1. [扩展]装饰器(es7,暂没有成为正式标准)
 class Text{
     @Obsolete
     show(){
         console.log("show已过时");
     }
 }

//看不到效果
 funtion Obsolete (target,methodName,descriptor){//对象,方法名,描述
     console.log(target,methodName,descriptor);
 }

类的继承

如果两个类A和B,如果可以描述为:B是A,则A和B形成继承关系
如果B是A,则:

  1. B继承A
  2. A派生B
  3. B是A的子类
  4. A是B的父类
    如果A是B的父类,则B会自动拥有A中的所有实例成员
//过去继承写法
function Animal(type,name,age,sex){
    this.type = type;
    this.name = name;
    this.age  = age;
    this.sex = sex;
}

Animal.prototype.print = function(){
    console.log(this.type,this.name,this.age,this.sex);
}

function Dog(name,age,sex){
    //借用父类的构造函数 
    Animal.call(this,"狗",name,age,sex);
}
Object.setPrototypeOf(Dog.prototype,Animal.prototype);//将Dog的隐式原型设置成Animal

let dog = new Dog("旺财",3,"male");
//es6继承写法
class Animal{
    construtor(type,name,age,sex){
        this.type = type;
        this.name = name;
        this.age  = age;
        this.sex = sex;
    }
}

class Dog extends Animal{
    construtor(name ,age,sex){
        //调用父类的构造函数 
        super("狗",name,age,sex);//或者Animal.call(this,"狗",name,age,sex);
    }
}

新的关键字:

  • extends:继承,用于类的定义
  • super直接当作函数调用,表示父类构造函数

注意:es6中规定如果类是子类必须在construtor中第一行手动调用父类的构造函数
如果子类不写contrutor,则会有默认的构造器,该构造器需要参数和父类一致,并且自动调用父类构造器

//子类不定construtor构造函数的默认情况  
class Animal{
    construtor(type,name,age,sex){
        this.type = type;
        this.name = name;
        this.age  = age;
        this.sex = sex;
    }
}
class Dog extends Animal{
   //默认构造器
   //这种情况下,如果子类构造函数参数与父类不同,则会出现参数错乱的情况
   construtor(type,name,age,sex){
       super(type,name,age,sex);
   }
}

【冷知识】

  • 用js制作抽象类
    • 抽象类:一般是父类,不能通过该类创建对象
class Animal{
    construtor(type,name,age,sex){
        this.type = type;
        this.name = name;
        this.age  = age;
        this.sex = sex;
    }
}
class Dog extends Animal{
    construtor(name ,age,sex){
        super("狗",name,age,sex);
    }
}
let dog = new Animal("狗","旺财",3,"male");//逻辑不正确,不应该用Animal类创建一个Dog类,Animal类是抽象的

//解决方法
class Animal{
    construtor(type,name,age,sex){
        if(new.target === Animal){//利用new.target
            throw new Error("你不能直接创建Animal的对象,应该通过子类创建");
        }
        this.type = type;
        this.name = name;
        this.age  = age;
        this.sex = sex;
    }
}
class Dog extends Animal{
    construtor(name ,age,sex){
        super("狗",name,age,sex);
    }
}
let dog = new Dog("旺财",3,"male");

let dog = new Animal("狗","旺财",3,"male");//出错

  • 正常情况下,this始终指向具体的类的对象
原创文章 14 获赞 17 访问量 3788

猜你喜欢

转载自blog.csdn.net/qq_45472813/article/details/105558017