ES6必知必会 (六)—— Class
1.在之前的JS面向对象编程中,如果定义一个构造函数,一般来说是这样:
function Person( name , age ) {
this.name = name;
this.age = age;
}
Person.prototype.say = function(){
return 'My name is ' + this.name + ', I am ' + this.age + ' years old';
}
这种写法跟传统的面向对象语言(比如 C++ 和 Java)差异很大,对于一些新学习JS的程序员来说不太容易理解,ES6 引入了 Class(类)这个概念,提供了更接近传统语言的写法,上述代码用 ES6 实现就是:
class Person {
constructor( name , age ) {
this.name = name;
this.age = age;
}
say() {
return return 'My name is ' + this.name + ', I am ' + this.age + ' years old';
}
}
上述代码中的constructor方法,这就是构造方法,而this关键字则代表实例对象
2.constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,会被默认添加一个空的constructor方法;
class Person {
}
// 等同于
class Person {
constructor() {}
}
3.constructor方法默认返回实例对象(即this),完全可以指定返回另外一个对象,但实际开发中不建议这么做;
class Foo {
constructor() {
return Object.create(null);
}
}
new Foo() instanceof Foo //false
此时constructor函数返回一个全新的对象,结果导致实例对象不是Foo类的实例,因此会返回 false;
4.使用new运算符用于生成类的实例对象,如果忘记加上new,像函数那样调用Class,将会报错;
class Person {
// ...
}
// 报错
var person = Person();
// 正确
var person = new Person();
5.实例的属性除非显式定义在其本身(即定义在this对象上),否则都是定义在原型上(即定义在class上),并且,类的所有实例共享一个原型对象
class Person {
//自身属性
constructor( name , age ) {
this.name = name;
this.age = age;
}
//原型对象的属性
say() {
return 'My name is ' + this.name + ', I am ' + this.age + ' years old';
}
}
var person = new Person( 'Jack' , 23);
person.hasOwnProperty('name') // true
person.hasOwnProperty('age') // true
person.hasOwnProperty('say') // false
person.__proto__.hasOwnProperty('say') // true
上述代码中,name 和 age 实例对象person自身的属性(因为定义在this变量上) ,所以hasOwnProperty方法返回true,而say是原型对象的属性(因为定义在Person类上),所以hasOwnProperty方法返回false;
6.与函数一样,可以使用表达式的形式定义一个类,即
const MyClass = class Me {
getClassName() {
return Me.name;
}
}
值得注意的是,这个类的名字是MyClass而不是Me,Me只在 Class 的内部代码可用,用来指代当前类;如果类的内部没用到的话,可以省略Me,写成下面的形式:
const MyClass = class {
getClassName() {
return Me.name;
}
}
7.采用 Class 表达式,可以写出立即执行的 Class。
let Person = new class {
constructor(name , age ) {
this.name = name;
this.age = age;
}
say() {
return 'My name is ' + this.name + ', I am ' + this.age + ' years old';
}
}('Jack' , 23 );
Person.say(); // 'My name is Jack, I am 23 years old'
8.ES6中类不存在变量提升,不会把类的声明提升到代码头部,即如果类使用在前,定义在后,这样会报错;
new Person(); //Uncaught ReferenceError : Person is not defined
class Person{}
9.跟ES5一样,ES6的类定义中,也不支持私有属性和私有方法,只能通过变通的方法模拟实现(命名上加下划线等);
10.可以在一个类的方法前,加上static关键字,声明其为‘静态方法’,这样就表示该方法不会被实例继承,而是直接通过类来调用;
class Foo {
static classMethod() {
return 'Hello World';
}
}
Foo.classMethod() // 'Hello World'
var foo = new Foo();
foo.classMethod() // TypeError: foo.classMethod is not a function
11.父类的静态方法,可以被子类继承,也可以从super对象上调用。
class Parent {
static classMethod() {
return 'Hello World';
}
}
//子类继承
class Child extends Parent {
}
Child.classMethod() // 'Hello World'
//super对象上调用
class Child extends Parent {
static classMethod() {
return super.classMethod();
}
}
Child.classMethod() // 'Hello World'
12.静态属性指的是 Class 本身的属性,即Class.propName,而不是定义在实例对象(this)上的属性,并且目前只能有以下方式定义:
class Foo {
}
Foo.prop = 1;
Foo.prop // 1
13.Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多;
class Parent {
//
}
//子类继承
class Child extends Parent {
}
上面代码定义了一个Child类,该类通过extends关键字,继承了Parent类的所有属性和方法;
14.子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象;
class Parent {
constructor(name , age ) {
this.name = name;
this.age = age;
}
}
//子类继承
class Child extends Parent {
constructor( name , age , hobby ) {
super( name , age ); // 调用父类的constructor( name , age )
this.hobby = hobby;
}
say(){
return 'My name is ' + this.name + ', I am ' + this.age + ' years old , I like ' + this.hobby;
}
}
15.super关键字,既可以当作函数使用,也可以当作对象使用:
作为函数调用时,代表父类的构造函数,并且只能用在子类的构造函数之中,用在其他地方就会报错;
<pre>
class A {}class B extends A {
m() {
super(); // 报错
}
}
</pre>作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类
<pre>
class A {
p() {
return 2;
}
}class B extends A {
constructor() {
super();
console.log(super.p()); // 2
}
}let b = new B();
</pre>
需要注意的是,super指向的是父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super调用的
class A {
constructor() {
this.p = 2;
}
}
class B extends A {
get m() {
return super.p;
}
}
let b = new B();
b.m // undefined
16.ES6 规定,通过super调用父类的方法时,super会绑定子类的 this ;
class A {
constructor() {
this.x = 1;
}
print() {
console.log(this.x);
}
}
class B extends A {
constructor() {
super();
this.x = 2;
}
m() {
super.print();
}
}
let b = new B();
b.m() // 2
上面代码中,super.print()虽然调用的是A.prototype.print(),但是A.prototype.print()会绑定子类B的this,导致输出的是2,而不是1。也就是说,实际上执行的是super.print.call(this)。
17.由于绑定子类的this,因此如果通过super对某个属性赋值,这时super就是this,赋值的属性会变成子类实例的属性;
class A {
constructor() {
this.x = 1;
}
}
class B extends A {
constructor() {
super();
this.x = 2;
super.x = 3;
}
print(){
console.log(super.x); // undefined
console.log(this.x); // 3
}
}
let b = new B();
b.print();
上面代码中,super.x 赋值为3,这时等同于对this.x赋值为3。而当读取super.x的时候,读的是A.prototype.x,而A的原型上没有x属性,所以返回undefined。
18.如果super作为对象,用在静态方法之中,这时super将指向父类,而不是父类的原型对象。
class Parent {
static myMethod(msg) {
console.log('static');
}
myMethod(msg) {
console.log('instance');
}
}
class Child extends Parent {
static myMethod() {
super.myMethod();
}
myMethod(msg) {
super.myMethod();
}
}
Child.myMethod(); // static
var child = new Child();
child.myMethod(); // instance
上述代码表明super在静态方法之中指向父类,在普通方法之中指向父类的原型对象。
19.Class 作为构造函数的语法糖,同时有prototype属性和 _proto_属性,因此同时存在两条继承链
- 子类的_proto_属性,表示构造函数的继承,总是指向父类。
- 子类prototype属性的_proto_属性,表示方法的继承,总是指向父类的prototype属性
<pre>
class A {
}
class B extends A {
}
B.\__proto__ === A // true
B.prototype.\__proto__ === A.prototype // true
</pre>
20.extends关键字不仅可以用来继承类,还可以用来继承原生的构造函数。因此可以在原生数据结构的基础上,定义自己的数据结构,下面就是定义了一个带版本功能的数组例子。
class VersionedArray extends Array {
constructor() {
super();
this.history = [[]];
}
commit() {
this.history.push(this.slice());
}
revert() {
this.splice(0, this.length, ...this.history[this.history.length - 1]);
}
}
var x = new VersionedArray();
x.push(1);
x.push(2);
x // [1, 2]
x.history // [[]]
x.commit();
x.history // [[], [1, 2]]
x.push(3);
x // [1, 2, 3]
x.history // [[], [1, 2]]
x.revert();
x // [1, 2]
ES6必知必会 (六)—— Class的更多相关文章
- Django框架之第六篇(模型层)--单表查询和必知必会13条、单表查询之双下划线、Django ORM常用字段和参数、关系字段
单表查询 补充一个知识点:在models.py建表是 create_time = models.DateField() 关键字参数: 1.auto_now:每次操作数据,都会自动刷新当前操作的时间 2 ...
- 2015 前端[JS]工程师必知必会
2015 前端[JS]工程师必知必会 本文摘自:http://zhuanlan.zhihu.com/FrontendMagazine/20002850 ,因为好东东西暂时没看懂,所以暂时保留下来,供以 ...
- [ 学习路线 ] 2015 前端(JS)工程师必知必会 (2)
http://segmentfault.com/a/1190000002678515?utm_source=Weibo&utm_medium=shareLink&utm_campaig ...
- mysql必知必会
春节放假没事,找了本电子书mysql必知必会敲了下.用的工具是有道笔记的markdown文档类型. 下面是根据大纲已经敲完的章节,可复制到有道笔记的查看,更美观. # 第一章 了解SQL## 什么是S ...
- python网络爬虫,知识储备,简单爬虫的必知必会,【核心】
知识储备,简单爬虫的必知必会,[核心] 一.实验说明 1. 环境登录 无需密码自动登录,系统用户名shiyanlou 2. 环境介绍 本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到桌 ...
- 关于TCP/IP,必知必会的十个经典问题[转]
关于TCP/IP,必知必会的十个问题 原创 2018-01-25 Ruheng 技术特工队 本文整理了一些TCP/IP协议簇中需要必知必会的十大问题,既是面试高频问题,又是程序员必备基础素养. 一 ...
- Android程序员必知必会的网络通信传输层协议——UDP和TCP
1.点评 互联网发展至今已经高度发达,而对于互联网应用(尤其即时通讯技术这一块)的开发者来说,网络编程是基础中的基础,只有更好地理解相关基础知识,对于应用层的开发才能做到游刃有余. 对于Android ...
- 迈向高阶:优秀Android程序员必知必会的网络基础
1.前言 网络通信一直是Android项目里比较重要的一个模块,Android开源项目上出现过很多优秀的网络框架,从一开始只是一些对HttpClient和HttpUrlConnection简易封装使用 ...
- 脑残式网络编程入门(三):HTTP协议必知必会的一些知识
本文原作者:“竹千代”,原文由“玉刚说”写作平台提供写作赞助,原文版权归“玉刚说”微信公众号所有,即时通讯网收录时有改动. 1.前言 无论是即时通讯应用还是传统的信息系统,Http协议都是我们最常打交 ...
- msql 必知必会笔记
Edit Mysql 必知必会 第一章 理解SQL 什么是数据库 数据库(database) 保存有组织的数据的容器 什么是表 一组特定类型的数据的结构化清单 什么是模式 数据库和表的布局及特性的 ...
随机推荐
- ssm所需要的pom(jre8、tomcat8、spring4)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...
- 没的选择时,存在就是合理的::与李旭科书法字QQ聊天记录
2015,8,11,晚上,与李旭科书法字作者,在Q上聊了下 有些资料 涉及到字库设计.字库产业,对大家也有益处 按惯例 没细整理,直接发blog了 ps,9.11 靠,今天是911,早上查资料,在 f ...
- python使用set来去重碰到TypeError: unhashable type
新版:Python 的 unhashable type 错误分析及解决 python使用set来去重是一种常用的方法. 一般使用方法如下: # int a = [1, 2, 3, 4, 5, 1, 2 ...
- Vue学习笔记之Nodejs入门
0x00 前言 打开Nodejs英文网:https://nodejs.org/en/ 中文网:http://nodejs.cn/ 我们会发现这样一句话: 翻译成中文如下: Node.js 是一个基于 ...
- bzoj1626 / P2872 [USACO07DEC]道路建设Building Roads
P2872 [USACO07DEC]道路建设Building Roads kruskal求最小生成树. #include<iostream> #include<cstdio> ...
- 20145326 《Java程序设计》第4周学习总结
20145326 <Java程序设计>第4周学习总结 教材学习内容总结 第六章 一.何谓继承 1.继承共同行为 面向对象中,子类继承父类,避免重复的行为定义.不过并非为了避免重复定义行为就 ...
- Gym 101246J Buoys(三分查找)
http://codeforces.com/gym/101246/problem/J 题意: 给定x轴上的n个点的坐标,按顺序从左到右给出,现在要使得每个点的间距相同,可以移动每个点的坐标,但是不能改 ...
- 51Nod 1737 配对(树的重心)
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1737 题意: 思路: 树的重心. 树的重心就是其所以子树的最大的子树结点 ...
- ggplot2作图详解7(完):主题(theme)设置
凡是和数据无关的图形设置内容理论上都可以归为主题类,但考虑到一些内容(如坐标轴)的特殊性,可以允许例外的情况.主题的设置相当繁琐,很容易就占用了 大量的作图时间,应尽量把这些东西简化,把注意力主要放在 ...
- IIS 7.5 配置 php 5.4.22 链接 sql 2008(用PDO链接数据库)
最近在接触PHP这块,关于在wndows系统下的php配置,虽然网上已经很多文章,但有时候有些配置找起也麻烦,所以分享给大家. 一.php 5.4.22 下载地址 http://windows.php ...