/*---------------------对象的扩展---------------------*/ //属性简写 ,属性名为变量名, 属性值为变量的值 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