es6新特性之 class 基本用法解析


Posted in Javascript onMay 05, 2018

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

总结

以上所述是小编给大家介绍的es6新特性之 class 基本用法解析,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

Javascript 相关文章推荐
JavaScript实现自己的DOM选择器原理及代码
Mar 04 Javascript
超棒的响应式布局jQuery插件Freetile.js
Nov 17 Javascript
javascript常用函数(1)
Nov 04 Javascript
jQuery实现每隔几条元素增加1条线的方法
Jun 27 Javascript
jQuery插件zTree实现的多选树效果示例
Mar 08 Javascript
vue2.0结合DataTable插件实现表格动态刷新的方法详解
Mar 17 Javascript
React-Native左右联动List的示例代码
Sep 21 Javascript
JS处理数据四舍五入(tofixed与round的区别详解)
Oct 26 Javascript
node.js基于fs模块对系统文件及目录进行读写操作的方法详解
Nov 10 Javascript
浅谈js中的bind
Mar 18 Javascript
有关vue 开发钉钉 H5 微应用 dd.ready() 不执行问题及快速解决方案
May 09 Javascript
vue生命周期钩子函数以及触发时机
Apr 26 Vue.js
JS同步、异步、延迟加载的方法
May 05 #Javascript
JavaScript生成指定范围随机数和随机序列的方法
May 05 #Javascript
JS文件中加载jquery.js的实例代码
May 05 #jQuery
关于js的三种使用方式(行内js、内部js、外部js)的程序代码
May 05 #Javascript
js动态引入的四种方法
May 05 #Javascript
关于HTML5的data-*自定义属性的总结
May 05 #Javascript
深入浅析Vue.js计算属性和侦听器
May 05 #Javascript
You might like
PHP静态新闻列表自动生成代码
2007/06/14 PHP
linux环境apache多端口配置虚拟主机的方法深入介绍
2013/06/09 PHP
jQuery+php实现ajax文件即时上传的详解
2013/06/17 PHP
php中 ob_start等函数截取标准输出的方法
2015/06/22 PHP
php PDO属性设置与操作方法分析
2018/12/27 PHP
ajaxControlToolkit AutoCompleteExtender的用法
2008/10/30 Javascript
IE iframe的onload方法分析小结
2010/01/07 Javascript
JavaScript 学习笔记(十三)Dom创建表格
2010/01/21 Javascript
基于jquery的跨域调用文件
2010/11/19 Javascript
JavaScript中的细节分析
2012/06/30 Javascript
JS中prototype的用法实例分析
2015/03/19 Javascript
js获取字符串字节数方法小结
2015/06/09 Javascript
jQuery代码实现发展历程时间轴特效
2015/07/30 Javascript
Node.js中使用mongoose操作mongodb数据库的方法
2017/09/12 Javascript
vue轮播图插件vue-awesome-swiper
2017/11/27 Javascript
javascript按顺序加载运行js方法
2017/12/01 Javascript
vue2.0 常用的 UI 库实例讲解
2017/12/12 Javascript
vue+canvas实现炫酷时钟效果的倒计时插件(已发布到npm的vue2插件,开箱即用)
2018/11/05 Javascript
jquery将json转为数据字典的实例代码
2019/10/11 jQuery
Vue打包部署到Nginx时,css样式不生效的解决方式
2020/08/03 Javascript
python调用cmd命令行制作刷博器
2014/01/13 Python
Python 200行代码实现一个滑动验证码过程详解
2019/07/11 Python
Pycharm 2020最新永久激活码(附最新激活码和插件)
2020/09/17 Python
python读取tif图片时保留其16bit的编码格式实例
2020/01/13 Python
tensorflow mnist 数据加载实现并画图效果
2020/02/05 Python
使用TensorFlow搭建一个全连接神经网络教程
2020/02/06 Python
详解Django中的FBV和CBV对比分析
2021/03/01 Python
管理站站长岗位职责
2013/11/27 职场文书
学生会招新策划书
2014/02/14 职场文书
房地产资料员岗位职责
2014/07/02 职场文书
关于读书的演讲稿300字
2014/08/27 职场文书
党的群众路线教育实践活动个人对照检查材料(乡镇)
2014/11/05 职场文书
2014年科普工作总结
2014/12/06 职场文书
面试复试通知单
2015/04/24 职场文书
教你怎么用PyCharm为同一服务器配置多个python解释器
2021/05/31 Python
解决spring.thymeleaf.cache=false不起作用的问题
2022/06/10 Java/Android