首頁 >web前端 >js教程 >es6中Class特性使用詳解

es6中Class特性使用詳解

php中世界最好的语言
php中世界最好的语言原創
2018-05-12 13:56:551835瀏覽

這次帶給大家es6中Class特性使用詳解,es6中Class特性使用的注意事項有哪些,下面就是實戰案例,一起來看一下。

javaScript 語言中,產生實例物件的傳統方法是透過建構函數,與傳統的物件導向語言(例如C 和Java )差異很大,ES6 提供了更接近傳統語言的寫法,引入了class(類別)這個概念,作為物件的模板。透過class關鍵字,可以定義類別。

es6 class 與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写法:
function Animate(name){
  this.name = name;
}
Animate.prototype.getname = function(){
  console.log(this.name)
}
var p =new Animate("lity");
p.getname();
//二.ES6,面向对象的写法,calss,
class Person{
  //constructor():构造方法是默认方法,new的时候回自动调用,如果没有显式定义,会自动添加
  //1.适合做初始化数据
  //2.constructor可以指定返回的对象
  constructor(name,age){
     this.name = name;
     this.age = age;
  }
  getval(){
    console.log(`你是${this.name},${this.age}岁`);
  }
}      
var c1 = new Person("lity",20); 
c1.getval();

 ES6 的class可以看作只是一個語法糖,它的絕大部分功能,ES5 都可以做到

注意:class 類別的本質還是一個函數,類別本身就指向建構子。

typeof Person  //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" in c1)//原型上存在,true
    console.log("name" in c1)//constructor(自己上存在),true
 //6.自定义检测属性是否是存在
    function hasproperty(attr,obj){
       return obj.hasOwnProperty(attr)&&(attr in obj);
    }
    console.log(hasproperty("name",c1));//true;

2.表達式寫法

//class表达式
const Myclass = class Me{//这里的Me是没有作用的
  constructor(name,jog){
    this.name = name;
    this.jog = jog;
  }
  getval(){
    console.log(`name is ${this.name},job is a ${this.jog}`);
  }
}
 var obj1 = new Myclass("lylt","teacher");
 obj1.getval();

3.class的私有方法(ES6不提供寫法)和私有屬性(也不提供寫法,提案用#識別)

      所謂私有方法和私有屬性,是指只能在類別的內部使用,不能在類別外部呼叫

 4.ES6規定Class類別沒有靜態屬性,只有靜態方法:static

     所謂靜態,不需要實例化對象,直接呼叫

class Foo {
   static classMethod() {
      return 'lity';
    }
 }
 console.log(Foo.classMethod()) // 'hello'

5.new.target屬性

new是在建構函數產生實例的指令,ES6為new提供了一個屬性.target,

 傳回透過new 指令實例物件的class(建構子),一般用於類別的內部

//ES5:原始写法对象
function objtarge(name){
  if(new.target==undefined){
    throw new Error("必须实例化对象");
  }else{
    this.name = name
  }
}
var targets = new objtarge("litys");
console.log(targets.name);//litys
//es6写法:class内部使用new.target,返回当前的calss
class caltartget{
  constructor(name){
    console.log(new.target==caltartget);//true
    if(new.target!==caltartget){
      throw new Error("实例化对象不是caltrget");
    }else{
      this.name = name;
    }
  }
}
var caltart = new caltartget("lity");
console.log(caltart.name);//lity

6.this指向

 類別的方法內部如果含有this,它預設指向類別的實例。但是,必須非常小心,一旦單獨使用該方法,很可能報錯

如下示例

class Logger {
 printName(name = 'there') {
  this.print(`Hello ${name}`);
 }
 print(text) {
  console.log(text);
 }
}
const logger = new Logger();
const { printName } = logger;
printName(); // TypeError: Cannot read property 'print' of undefined

分析以上示例:prinName 的方法中this,默認指向類Logger,但是將改方法單獨調用,就會報錯,this會指向所在運行的環境,所以因為找不到this.print()方法而報錯。

針對上述解決this指向的方法:

(1). 使用bind(this)

(2). 使用es6 的箭頭函數()=>{ }

(3).使用Proxy 代理

//1.bind()方法
class Logger {
 constructor() {
  this.printName = this.printName.bind(this);
 }
 // ...
}
//2.箭头函数 ()=>{}
class Logger {
 constructor() {
  this.printName = (name = 'there') => {
   this.print(`Hello ${name}`);
  };
 }
 // ...
}
//3. Porxy()
.................

7.class 的get() 和set() 方法

與ES5 一樣,在「類別」的內部可以使用get和set關鍵字,對某個屬性設定存值函數和取值函數,攔截該屬性的存取行為。

class MyClass {
 constructor() {
  // ...
 }
 get prop() {// 使用 get 拦截了该方法的返回值
  return 'getter';
 }
 set prop(value) {//当对该方法赋值时能获取到该赋值
  console.log('setter: '+value);
 }
}
let obj = new MyClass();
obj.prop = 123;
// setter: 123
inst.prop
// 'getter'

8.繼承

#

Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。

//es5 的继承
//父类
function Person(name,sex){
  this.name = name;//属性
  this.sex = sex;//属性       
}
//定义一个原型方法
Person.prototype.show = function(){
  console.log("我的姓名是"+this.name+"==="+"我的性别是"+this.sex)
}
//子类
function Worker(name,sex,job){      
  //构成函数伪装:使用call()方法绑定this,伪装继承父级的属性
  Person.call(this,name,sex);
  this.job = job;
}
//继承父类的原型方法:(介绍三种方法)
//写法一:通过遍历父级的原型一个个赋给子级的原型(es5 的原型是可枚举的,es6的不可以枚举)
(var i in Person.prototype){
  Worker.prototype[i] = Person.prototype[i];
}
//写法:重新new一个父级对象赋给子级的原型
Worker.prototype = new Person();
Worker.prototype.constructor = Worker;
//写法三:创建一个原型对象赋给子级的原型;(es5 推荐)
Worker.prototype = Object.create(Person.prototype);
Worker.prototype.constructor = Worker;
var workers = new Worker("小明","男","job")
//es6 的继承
class Person{
  constructor(name,sex){
    this.name = name;//属性
     this.sex = sex;//属性
   }
}
class Worker extends Person{
   constructor(name,sex,job){
     super();
     this.job =job;
   }
}
var workers = new Worker("小明","男","job")

8.1:super关键字:在子类中不同情况用法不同,既可以当作函数使用,也可以当作对象使用。

    (1):super作为函数,只能在constructor中使用:代表父类,返回子类的this

   (2):super作为对象,在普通函数中,cuper指向父类的原型对象,可以访问原型对象的属性和方法,注意,父类的实例的属性和方法是访问不了的

   (3):super作为对象,在静态方法中,cuper指向的是父类,不是父类的原型对象

示例分析如下:

//父类
class Aniamte{
  constructor(){
    if(new.target == Aniamte){
      throw new Error("本类不能实例化,只能有子类继承");
    }
  }
  //静态方法
  static getval(mgs){
    console.log("父类的static",mgs)
  }
  //普通方法      
  setname(){
    console.log("该方法有子类重写")
  }      
}
//子类
class Dog extends Aniamte{
  constructor(){
    super();//调用此方法,this才用可以用,代表父类的构造函数,返回的却是子类
    //super() ==父类.prototype.constructor.call(子类/this)
    console.log(this)//Dog {}
    this.age = 20;
    }
  //静态方法,super在静态方法中作为对象使用,指向父类;
  static getval(mgs){
    super.getval(mgs)//父类的static niceday
    console.log("子类的static",mgs)//子类的static niceday
  }
  setname(name){
    //普通方法,super作为对象使用,指向父类的原型对象,父类.prototype;
    super.setname();//该方法有子类重写
    this.name = name;
    return this.name
  }
};
Dog.getval("niceday");//静态方法,直接调用
//var parAni = new Aniamte();//报错
var dogs = new Dog();//new 一个示例对象
dogs.setname("DOYS");////DOYS

8.2.原生构造函数的继承,ES5不支持,ES6利用extend可以继承原生构造函数

//ESMAScript的构造函数有以下几种
/* Boolean()
* Unmber()
* String()
* Array()
* Date()
* Function()
* RegExp()
* Error()
* Object()
*/
//实例一:自定义类Myarray 继承了原生的数组的构造函数,拥有原生数组的属性和方法了
class Myarray extends Array{
  constructor(){
  super();
  console.log(this.constructor.name)//Myarray
  }
}
var myarr = new Myarray();
console.log(Object.prototype.toString.call(myarr));//[object Array]
myarr.push(1,2,1);
console.log(myarr.length)//3

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

React Form组件封装步骤详解

Vue数组变异实现详解

以上是es6中Class特性使用詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn