es6新特性之 class 基本用法解析
javaScript语言中,生成实例对象的传统方法是通过构造函数,与传统的面向对象语言(比如C++和Java)差异很大,ES6提供了更接近传统语言的写法,引入了class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。
es6class与es5的面向对象的区别:
1.写法不同,使用关键字class
2.当new一个实例,默认有一个constructor方法,且默认返回实例对象(this),也可以返回另一对象
3.类的所有方法都在prototype属性上,但是不可枚举,且每方法结束不能使用分号
4.类的调用必须通过new一个实例,且类的内部默认使用严格模式
5.不存在变量提升,必须先声明,再调用
6.class的this默认指向当前类
7.class的静态方法,使用关键字static,不需new,直接通过类来调用
8.实例属性和静态属性的写法,实例属性在类的内部直接使用等式(=)写法,也可以写在constructor方法里,静态属性只需在实例属性前加一个关键字static即可
9.类的继承使用关键字extends,继承机制与es5完全不同,
es5的继承原理:先new子类的实例对象this,再通过将父类的方法和属性添加到子类的this上(parents.call(this))。
Es6的继承原理:先创造父类的实例对象this,所以要构造函数constructor()访问父类的属性使用this,必须先调用super()方法;再通过子类的constructor()来修改this
10.类的继承可以继承原生的构造函数,es5不可以
1.一般写法(es5与es6)
//一.ES5写法: functionAnimate(name){ this.name=name; } Animate.prototype.getname=function(){ console.log(this.name) } varp=newAnimate("lity"); p.getname(); //二.ES6,面向对象的写法,calss, classPerson{ //constructor():构造方法是默认方法,new的时候回自动调用,如果没有显式定义,会自动添加 //1.适合做初始化数据 //2.constructor可以指定返回的对象 constructor(name,age){ this.name=name; this.age=age; } getval(){ console.log(`你是${this.name},${this.age}岁`); } } varc1=newPerson("lity",20); c1.getval();
ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到
注意:class类的本质还是一个函数,类本身就指向构造函数。
typeofPerson//function Person===Person.prototype.constructor//true
我们使用Object的一些属性或者方法检测一下用es6写的实例对象
//1.查看实例对象c1的__proto__是否指向Person的原型(Person.prototype) console.log(c1.__proto__==Person.prototype)//true console.log(c1.__proto__)//原型对象的所有方法 //2.isPrototypeOf:检测实例对象是否是某个函数的原型 console.log(Person.prototype.isPrototypeOf(c1));//true //3.constructor:查看某个对象的构造函数 console.log(c1.constructor); //4.hasOwnProperty:检测某个属性是否是自己的属性;不是原型对象上的属性和方法 console.log(c1.hasOwnProperty("name"))//true; //5.in:通过in可以检测属性是否在自己中(this)或者是原型中存在 console.log("getval"inc1)//原型上存在,true console.log("name"inc1)//constructor(自己上存在),true //6.自定义检测属性是否是存在 functionhasproperty(attr,obj){ returnobj.hasOwnProperty(attr)&&(attrinobj); } console.log(hasproperty("name",c1));//true;
2.表达式写法
//class表达式 constMyclass=classMe{//这里的Me是没有作用的 constructor(name,jog){ this.name=name; this.jog=jog; } getval(){ console.log(`nameis${this.name},jobisa${this.jog}`); } } varobj1=newMyclass("lylt","teacher"); obj1.getval();
3.class的私有方法(ES6不提供写法)和私有属性(也不提供写法,提案用#识别)
所谓私有方法和私有属性,是指只能在类的内部使用,不能在类外部调用
4.ES6规定Class类没有静态属性,只有静态方法:static
所谓静态,不需要实例化对象,直接调用
classFoo{ staticclassMethod(){ return'lity'; } } console.log(Foo.classMethod())//'hello'
5.new.target属性
new是在构造函数生成实例的命令,ES6为new提供了一个属性.target,
返回通过new命令实例对象的class(构造函数),一般用于类的内部
//ES5:原始写法对象 functionobjtarge(name){ if(new.target==undefined){ thrownewError("必须实例化对象"); }else{ this.name=name } } vartargets=newobjtarge("litys"); console.log(targets.name);//litys //es6写法:class内部使用new.target,返回当前的calss classcaltartget{ constructor(name){ console.log(new.target==caltartget);//true if(new.target!==caltartget){ thrownewError("实例化对象不是caltrget"); }else{ this.name=name; } } } varcaltart=newcaltartget("lity"); console.log(caltart.name);//lity
6.this指向
类的方法内部如果含有this,它默认指向类的实例。但是,必须非常小心,一旦单独使用该方法,很可能报错
如下示例
classLogger{ printName(name='there'){ this.print(`Hello${name}`); } print(text){ console.log(text); } } constlogger=newLogger(); const{printName}=logger; printName();//TypeError:Cannotreadproperty'print'ofundefined
分析以上示例:prinName的方法中this,默认指向类Logger,但是将改方法单独调用,就会报错,this会指向所在运行的环境,所以因为找不到this.print()方法而报错。
针对以上解决this指向的方法:
(1).使用bind(this)
(2).使用es6的箭头函数()=>{}
(3).使用Proxy代理
//1.bind()方法 classLogger{ constructor(){ this.printName=this.printName.bind(this); } //... } //2.箭头函数()=>{} classLogger{ constructor(){ this.printName=(name='there')=>{ this.print(`Hello${name}`); }; } //... } //3.Porxy() .................
7.class的get()和set()方法
与ES5一样,在“类”的内部可以使用get和set关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
classMyClass{ constructor(){ //... } getprop(){//使用get拦截了该方法的返回值 return'getter'; } setprop(value){//当对该方法赋值时能获取到该赋值 console.log('setter:'+value); } } letobj=newMyClass(); obj.prop=123; //setter:123 inst.prop //'getter'
8.继承
Class可以通过extends关键字实现继承,这比ES5的通过修改原型链实现继承,要清晰和方便很多。
//es5的继承 //父类 functionPerson(name,sex){ this.name=name;//属性 this.sex=sex;//属性 } //定义一个原型方法 Person.prototype.show=function(){ console.log("我的姓名是"+this.name+"==="+"我的性别是"+this.sex) } //子类 functionWorker(name,sex,job){ //构成函数伪装:使用call()方法绑定this,伪装继承父级的属性 Person.call(this,name,sex); this.job=job; } //继承父类的原型方法:(介绍三种方法) //写法一:通过遍历父级的原型一个个赋给子级的原型(es5的原型是可枚举的,es6的不可以枚举) (variinPerson.prototype){ Worker.prototype[i]=Person.prototype[i]; } //写法:重新new一个父级对象赋给子级的原型 Worker.prototype=newPerson(); Worker.prototype.constructor=Worker; //写法三:创建一个原型对象赋给子级的原型;(es5推荐) Worker.prototype=Object.create(Person.prototype); Worker.prototype.constructor=Worker; varworkers=newWorker("小明","男","job") //es6的继承 classPerson{ constructor(name,sex){ this.name=name;//属性 this.sex=sex;//属性 } } classWorkerextendsPerson{ constructor(name,sex,job){ super(); this.job=job; } } varworkers=newWorker("小明","男","job")
8.1:super关键字:在子类中不同情况用法不同,既可以当作函数使用,也可以当作对象使用。
(1):super作为函数,只能在constructor中使用:代表父类,返回子类的this
(2):super作为对象,在普通函数中,cuper指向父类的原型对象,可以访问原型对象的属性和方法,注意,父类的实例的属性和方法是访问不了的
(3):super作为对象,在静态方法中,cuper指向的是父类,不是父类的原型对象
示例分析如下:
//父类 classAniamte{ constructor(){ if(new.target==Aniamte){ thrownewError("本类不能实例化,只能有子类继承"); } } //静态方法 staticgetval(mgs){ console.log("父类的static",mgs) } //普通方法 setname(){ console.log("该方法有子类重写") } } //子类 classDogextendsAniamte{ constructor(){ super();//调用此方法,this才用可以用,代表父类的构造函数,返回的却是子类 //super()==父类.prototype.constructor.call(子类/this) console.log(this)//Dog{} this.age=20; } //静态方法,super在静态方法中作为对象使用,指向父类; staticgetval(mgs){ super.getval(mgs)//父类的staticniceday console.log("子类的static",mgs)//子类的staticniceday } setname(name){ //普通方法,super作为对象使用,指向父类的原型对象,父类.prototype; super.setname();//该方法有子类重写 this.name=name; returnthis.name } }; Dog.getval("niceday");//静态方法,直接调用 //varparAni=newAniamte();//报错 vardogs=newDog();//new一个示例对象 dogs.setname("DOYS");////DOYS
8.2.原生构造函数的继承,ES5不支持,ES6利用extend可以继承原生构造函数
//ESMAScript的构造函数有以下几种 /*Boolean() *Unmber() *String() *Array() *Date() *Function() *RegExp() *Error() *Object() */ //实例一:自定义类Myarray继承了原生的数组的构造函数,拥有原生数组的属性和方法了 classMyarrayextendsArray{ constructor(){ super(); console.log(this.constructor.name)//Myarray } } varmyarr=newMyarray(); console.log(Object.prototype.toString.call(myarr));//[objectArray] myarr.push(1,2,1); console.log(myarr.length)//3
总结
以上所述是小编给大家介绍的es6新特性之class基本用法解析,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!