Es6对象的扩展和Class类的基础知识笔记

/*---------------------对象的扩展---------------------*/
//属性简写 ,属性名为变量名, 属性值为变量的值
export default function(){
    const a='aaa';
    const b={a};
    console.info(b);//b==={a: "aaa"}

    function d(x,y){
        //相当于 return {x:x,y:y} //属性的简写
        return console.info({x,y})
    }
    d(1,2); //{x: 1, y: 2}

    const name='leyi',petName='jiucaiqiezi';
    const e={
         name,
         petName, //属性简写 petName:petName
         sayHello(){console.info({name,petName})} //函数简写
    };
    e.sayHello(); //{name: "leyi", petName: "jiucaiqiezi"}
}

//属性名表达式
const f={};
f.name='leyi';
f['pet'+'name']='jiucaiqieizi';
console.info(f); //{name: "leyi", petName: "jiucaiqiezi"}

const fname='name';
const g={
     [fname]:'leyi',
     ['pet'+'name']:'jiucaiqieizi',
     ['say'+'Hello'](){
         console.info(this.fname);
     },
};
console.info(g);//{name: "leyi", petName: "jiucaiqiezi"}
g.sayHello();//表达式可以用于定义方法名

//属性名表达式如果是一个对象,默认情况下会自动将对象转为字符串[object Object]
const h={'name':'leyi'};
const i={
    [h]:'jiucaiqiezi',
};
console.info(i); //{[object Object]: "jiucaiqiezi"}

//Object.is  用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致
console.info(Object.is(+0,-0)); //false 不会转换数据类型

//Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target) 跟$.extend()差不多
//如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性

const j={"name":"hello"};
const k={"petName":"jiucaiqiezi",obj:{'color':'red'}};
//不是对象的参数会转成对象
const l=Object.assign({"name":"leyi"},j,k,undefined,null,'wo'); //undefined和null无法转成对象,非首参数就会跳过
console.info(l);
//Object.assign方法实行的是浅拷贝,而不是深拷贝。如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用
k.obj.color='green';
console.info(l);//{0: "w", 1: "o", name: "hello", petName: "jiucaiqiezi", obj: Object} obj{"color:green}
//Object.assign可以用来处理数组,但是会把数组视为对象。
console.info(Object.assign([1,2,3])); //{0:1,1:2,2:3}
console.info(Object.assign([1,2,3],[4,5,6])); //[4, 5, 6]

//属性的遍历
//for...in循环遍历对象自身的和继承的可枚举属性
//Object.keys(obj) 返回一个数组,包括对象自身的(不含继承的)所有可枚举属性 所以一般用Object.keys()代替for...in循环
const m={'name':'leyi',"petName":'jiucaiqiezi'};
console.info("Object.keys",Object.keys(m)); //["name", "petName"]
//Object.getOwnPropertyNames 返回一个数组,包含其自身的可枚举和不可枚举属性的名称
const n=[1,2,3,4,5];
console.info("Object.getOwnPropertyNames",Object.getOwnPropertyNames(n)); //["0", "1", "2", "3", "4", "length"]

function OParent(){
    this.pAttr=0;
}
function OChild(){
    this.cttr1=1;
    this.cttr2=2
}
OChild.prototype=new OParent();
//该方法不会获取到原型链上的属性
console.info(Object.getOwnPropertyNames(new OChild())); //["cttr1", "cttr2"]

//Object.setPrototypeOf方法用来设置一个对象的prototype对象并返回该对象 prototype
const proto={'petName':'jiucaiqiezi'};
const obj={"name":'leyi'};
Object.setPrototypeOf(obj,proto);
console.info(obj.__proto__); //{petName: "jiucaiqiezi"}
//getPrototypeOf用于读取一个对象的原型对象
console.info(Object.getPrototypeOf(new OChild())); //{pAttr: 0}

//Object.keys  Object.values Object.entries
console.info(Object.keys(obj)); //["name"]
console.info(Object.values(obj));//["leyi"]
console.info(Object.entries(obj)); //[['name','leyi']];

//通过Object.entries将对象转为map结构
const p={'name':'leyi','petName':'jiucaiqiezi'};
const pMap=new Map(Object.entries(p));
console.info(pMap.size);
const q = { one: 1, two: 2 };
for (let [k, v] of new Map(Object.entries(q))) {
    console.info(`${k}------${v}`);
}

/*---------------------class基本语法---------------------*/
//定义类
//定义“类”的方法的时候,前面不需要加上function这个关键字,直接把函数定义放进去了就可以了。另外,方法之间不需要逗号分隔,加了会报错。
class R{
  constructor(ag1,ag2){
      this.ag1=ag1;
      this.ag2=ag2;
  }
  hello(){
      return `
      ${this.ag1}
      ${this.ag2}
      `
  }
}
const s=new R(1,2);
console.info(s.hello()); //1 2

//类的所有方法都定义在类的prototype属性上面
class T{
    tt(){}
    ttt(){}
}
//上面等同于
T.prototype={
    tt(){},
    ttt(){},
};

//类的方法都定义在prototype对象上面,所以类的新方法可以添加在prototype对象上面。Object.assign方法可以很方便地一次向类添加多个方法
Object.assign(T.prototype,{
    tttt(){},
    ttttt(){},
});
console.info(Object.getPrototypeOf(new T()));//{tt: function, ttt: function, tttt: function, ttttt: function}

//constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,
// 如果没有显式定义,一个空的constructor方法会被默认添加。
//constructor方法默认返回实例对象
//类的所有实例共享一个原型对象
//可以通过实例的__proto__属性为Class添加方法
new T().__proto__.tttttt=function(){};
console.info(Object.getPrototypeOf(new T()));//{tt: function, ttt: function, tttt: function, ttttt: function, tttttt: function}

//class的继承
//Class之间可以通过extends关键字实现继承
class U extends R{
    constructor(ag1,ag2,name){
        super(ag1,ag2);  //super关键字,它在这里表示父类的构造函数,用来新建父类的this对象
        //this 指向当前类 super(ag1,ag2).call(this)
        this.name='leyi';
    }
    hi(){
        return this.name+'-----'+this.ag1+'-----'+this.ag2
    }
}
const v=new U(1,2);
v.hi();
console.info(v,v instanceof U,v instanceof R);//{ag1: 1, ag2: 2, name: "leyi"} true true

//super作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。
class S1{
    constructor(){
    }
    static sayhi(){
        console.info('sayhi');
    }
    sayhello(){
        console.info('sayhello');
    }
}
S1.attr1='attr1';

class S2 extends S1{
    constructor(){
        super();
    }
    static hi(){
        super.sayhi();//super作为对象时,在静态方法中,指向父类
        console.info( super.attr1);//attr1
    }
    hello(){
        super.say1; //super作为对象时,在普通方法中,指向父类的原型对象
    }
}

new S2().hello();
S2.hi();

//Class作为构造函数的语法糖,同时有prototype属性和__proto__属性
//子类的__proto__属性,表示构造函数的继承,总是指向父类
//子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性。
class W{
}
class X extends W{
    constructor(){
        super();
    }
}
console.info(X.__proto__==W,X.prototype.__proto__= W.prototype);// true true

//Object.getPrototypeOf方法可以用来从子类上获取父类,也可以用来判断一个类是否继承了另一个类
console.info(Object.getPrototypeOf(X)===W);//true X.__proto__==W

//类的静态方法
//该方法不会被实例继承,而是直接通过类来调用
class Y{
    static method1(){
        return 'hello static!'
    }
}
console.info("Y.method1()------------->",Y.method1());

//父类的静态方法,可以被子类继承
class YY extends Y{
    static method2(){
        return super.method1(); //静态方法也是可以从super对象上调用
    }
}
console.info("YY.method1()------------->",YY.method1());
console.info("YY.method2()------------->",YY.method2());

//ES6规定Class内部只有静态方法,没有静态属性
//class 的静态属性 静态属性指的是Class本身的属性 和实例属性
class Z{
    //static attr0='attr0'; //Es7的提案 定义类的静态属性,目前不支持
    //attr0='attr0'; //定义类的实例属性 不支持
    constructor(){
        this.attr0='attr0';
        console.info(this.attr0);
    }
}
Z.attr1='attr1'; //定义类的静态属性
console.info("new Z().attr0---->",new Z().attr0);//attr0

//new.atrget 属性 返回new命令作用于的那个构造函数。如果构造函数不是通过new命令调用的,new.target会返回undefined

class AA{
    constructor(){
        console.info("new.target----->",new.target===AA); //new.target-----> true
    }
}
new AA();

//子类继承父类时,new.target会返回子类
class AAA extends AA{
    constructor(){
        super(); //new.target-----> false
        console.info("new.target----->",new.target===AAA);//new.target-----> true
    }
}
new AAA();

//利用这个特点,可以写出不能独立使用、必须继承后才能使用的类
class BB{
    constructor(){
        if(new.target===BB){
            throw new Error('此类不能被实例化!');
        }
    }
}
class BBB extends BB{
    constructor(){
        super();
        this.name='leyi';
    }
    hello(){
        console.info("this.name----->",this.name);
    }
}

new BB(); //此类不能被实例化!
new BBB().hello(); //this.name-----> leyi

  

原文地址:https://www.cnblogs.com/leyi/p/6733855.html