ECMAScript6(ES6)标准之class类的定义、继承及静态方法
2016-12-26 20:32
681 查看
众所周知,JavaScript中是没有传统类的概念的
它利用原型链完成继承
对于当时刚学JavaScript的我来说,一时不好接受
声明的方式看起来非常奇怪
不过在我们的ES6中借鉴了很多语言的语法(Python、Java…)
这其中包括class类的概念
class不是新结构而是原型链的语法糖
早在ES4的时候,草案中就已经出现了class
不过ES4由于过于激进,和一系列问题
被大家抵制
不过大家现在完全不用担心ES6步ES4的后尘
(好奇的同学可以看看“传说”中的ES4草案:传送门)
下面再看看这个新的一等公民是怎样定义的
学习过C++或者Java的同学一定会感觉无比亲切
上面的代码利用ES6的class这样写
新的class写法让对象原型更加清晰
更像面向对象的编程语言
不过还是要注意
虽然是模仿传统的继承方式
但是只是语法糖
仍然使用的是[[prototype]]的委托机制
(包括后面谈到的继承,子类不会像其他语言一样拷贝父类的东西)
定义类方法前面没有function关键字
方法之间不能加“,”逗号
类没有提升行为
类内部定义方法不可枚举
函数是有提升行为的
所以下面的写法没有问题
但是类没有
下面的写法浏览器就会报错
类内部定义的方法是不可枚举的
我们可以用for-in验证
我们发现传统原型链打印了name,age,say
但是使用class方法只打印了name,age
上面的代码也可以这样写
类比于我们的函数表达式
以及函数的name属性
先定义一个父类
接着是子类的声明
这个子类的构造函数中出现了一个新的关键字super
没有它的话,就无法继承父类的实例属性
(子类中有constructor,内部就要有super)
(子类没有自己的this对象,需要继承父类的this对象再添加东西)
super指代父类的实例(父类的this对象)
这里的
换成我们ES5的继承大概是这个样子的
ES5的继承,
实质是先创造子类的实例对象this
然后再将父类的方法添加到this上面(Parent.apply(this))
ES6的继承,
实质是先创造父类的实例对象this(必须先调用super)
然后再用子类的构造函数修改this
它们的实现机制是不同的
所有类中定义的方法都会被实例继承
如果在类方法前加上static
就不会被实例继承,而是直接通过类来调用
静态方法也可以从super调用
子类调用父类的static方法也只能在静态函数中调用
ES6中类的相关知识就总结到这里了
==主页传送门==
它利用原型链完成继承
对于当时刚学JavaScript的我来说,一时不好接受
声明的方式看起来非常奇怪
不过在我们的ES6中借鉴了很多语言的语法(Python、Java…)
这其中包括class类的概念
class不是新结构而是原型链的语法糖
早在ES4的时候,草案中就已经出现了class
不过ES4由于过于激进,和一系列问题
被大家抵制
不过大家现在完全不用担心ES6步ES4的后尘
(好奇的同学可以看看“传说”中的ES4草案:传送门)
类定义
我们先来看看我们一般的原型链方法function Person(name, age){ this.name = name; this.age = age; } Person.prototype.say = function(){ console.log('my name is ' + this.name + ', ' + this.age + ' years old'); } var person = new Person('payen', '19'); person.say(); //my name is payen, 19 years old
下面再看看这个新的一等公民是怎样定义的
学习过C++或者Java的同学一定会感觉无比亲切
上面的代码利用ES6的class这样写
class Person { constructor(name, age){ this.name = name; this.age = age; } say(){ console.log('my name is ' + this.name + ', ' + this.age + ' years old'); } } var person = new Person('payen', '19'); person.say(); //my name is payen, 19 years old
新的class写法让对象原型更加清晰
更像面向对象的编程语言
不过还是要注意
虽然是模仿传统的继承方式
但是只是语法糖
仍然使用的是[[prototype]]的委托机制
(包括后面谈到的继承,子类不会像其他语言一样拷贝父类的东西)
注意事项
这里需要注意的有定义类方法前面没有function关键字
方法之间不能加“,”逗号
类没有提升行为
类内部定义方法不可枚举
函数是有提升行为的
所以下面的写法没有问题
foo(); function foo(){ ... }
但是类没有
下面的写法浏览器就会报错
var person = new Person(); //错误 class Person{ ... }
类内部定义的方法是不可枚举的
我们可以用for-in验证
for(var prop in person){ console.log(prop); }
我们发现传统原型链打印了name,age,say
但是使用class方法只打印了name,age
类表达式
类的另一种定义方式就是类表达式上面的代码也可以这样写
var demo = class { constructor(name, age){ this.name = name; this.age = age; } say(){ console.log('my name is ' + this.name + ', ' + this.age + ' years old'); } } console.log(demo); var person = new demo('payen', '19'); <-- 注意 person.say(); //my name is payen, 19 years old
类比于我们的函数表达式
以及函数的name属性
function demo(){}; console.log(demo.name); //demo
var demo = function(){}; console.log(demo.name); //demo
var demo = function foo(){}; console.log(demo.name); //foo
class demo{} console.log(demo.name); //demo
let demo = class {}; console.log(demo.name); //demo
let demo = class foo{}; console.log(demo.name); //foo
类继承
类之间的继承可以通过extends关键字实现先定义一个父类
class Point{ constructor(x, y){ this.x = x; this.y = y; } toString(){ return '点坐标: ' + this.x + ',' + this.y; } } let fp = new Point(12, 34); console.log(fp.toString()); //"点坐标: 12,34"
接着是子类的声明
class ColoredPoint extends Point{ constructor(x, y, color){ super(x, y); this.color = color; } toString(){ return this.color + super.toString(); } } let sp = new ColoredPoint(56, 78, '红色'); console.log(sp.toString()); //"红色点坐标: 56,78"
这个子类的构造函数中出现了一个新的关键字super
没有它的话,就无法继承父类的实例属性
(子类中有constructor,内部就要有super)
(子类没有自己的this对象,需要继承父类的this对象再添加东西)
super指代父类的实例(父类的this对象)
这里的
super(x,y)就是调用父类的构造函数
super.toString()就是调用父类toString()方法
换成我们ES5的继承大概是这个样子的
function ColoredPoint(x, y) { Point.apply(this, [x, y]); } ColoredPoint.prototype = Object.create(Point.prototype, { toString: function() { ... } }); ColoredPoint.prototype.constructor = ColoredPoint;
ES5的继承,
实质是先创造子类的实例对象this
然后再将父类的方法添加到this上面(Parent.apply(this))
ES6的继承,
实质是先创造父类的实例对象this(必须先调用super)
然后再用子类的构造函数修改this
它们的实现机制是不同的
静态方法
类相当于实例中的原型所有类中定义的方法都会被实例继承
如果在类方法前加上static
就不会被实例继承,而是直接通过类来调用
class Foo{ static print(){ return 'hello world'; } } console.log(Foo.print()); //"hello world"
静态方法也可以从super调用
子类调用父类的static方法也只能在静态函数中调用
class Bar extends Foo{ static say(){ return super.print(); } } let b = new Bar(); console.log(Bar.print()); //"hello world" console.log(Bar.say()); //"hello world" console.log(b.say()); //报错
ES6中类的相关知识就总结到这里了
==主页传送门==
相关文章推荐
- ECMAScript6(ES6)标准之class类的定义、继承及静态方法
- ECMAScript6(ES6)标准之对象Object扩展方法及新特性
- ECMAScript6(ES6)标准之数组Array扩展方法
- javascript面向对象编程实现[定义(静态)属性方法--继承]
- ECMA2015(ES6)简单入门-3-迭代器-生成器-定义类-__静态方法__继承
- javascript面向对象编程实现[定义(静态)属性方法--继承]
- java静态方法的继承
- Java静态代码块、构造器、静态主方法以及继承后父类代码块的运行顺序
- Javascript 构造函数,公有,私有特权和静态成员定义方法
- 标准15针 VGA 显示接口定义及焊接方法
- objective-C 的OOP(上)--类定义、继承及方法调用
- 静态(static)方法的继承和重写
- 子类继承父类(重写父类的静态方法,子类方法必须也是静态的)
- Flex中的CSS: (9)可继承/不可继承样式的定义 以及Flex中的实现方法
- Flex中的CSS: (9)可继承/不可继承样式的定义 以及Flex中的实现方法 1
- 用static定义静态方法
- C#几个例子[静态构造函数,继承,虚方法]
- 静态数组的定义方法
- 抽象类中定义静态方法
- Java中静态变量与静态方法的继承