class
ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class
关键字,可以定义类。基本上,ES6的class
可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class
写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
class Person{
constructor(name,age){
this.name=name;
this.age=age;
}
Fun(){
return this.x
}
}
上面代码定义了一个“类”,可以看到里面有一个constructor
方法,这就是构造方法,而this
关键字则代表实例对象。也就是说,ES5 的构造函数Point
,对应 ES6 的Point
类的构造方法。
Point
类除了构造方法,还定义了一个toString
方法。注意,定义“类”的方法的时候,前面不需要加上function
这个关键字,直接把函数定义放进去了就可以了。另外,方法之间不需要逗号分隔,加了会报错。
使用的时候,也是直接对类使用 new 命令,跟构造函数的用法完全一致
class end{
bar(){
console.log("apple")
}
}
var i=new end();
i.bar()
构造函数的prototype
属性,在 ES6 的“类”上面继续存在。事实上,类的所有方法都定义在类的prototype
属性上面。
class Person {
constructor() {// ... }
toString() {// ...}
toValue() {// ...}
}
// 等同于
Person.prototype = {
constructor() {},
toString() {},
toValue() {},
};
rototype
对象的constructor
属性,直接指向“类”的本身,这与 ES5 的行为是一致的。
Point.prototype.constructor === Point // true
&enps; 不同的是,类的内部所有定义的方法,都是不可枚举的;而ES5的写法中,函数原型上的方法是可枚举的。
class Point {
constructor(x, y) {
// ...
}
toString() {
// ...
}
}
Object.keys(Point.prototype)
Object.getOwnPropertyNames(Point.prototype)
constructor 方法
constructor 方法是类的默认方法,创建类的实例化对象时被调用。
class cont{
constructor(){
console.log('我是constructor');
}
}
new cont();
class 定义类
(1)在 class 类上添加的属性都是在原型 prototype 上添加的
(2)new 实例的时候其实就是调用构造函数这个方法
(3)类的本质其实就是一个函数
(4)类中的this 指向实例对象
(5)添加的私有属性都在构造函数中添加
(6)每个构造方法都会默认返回实例对象this,如果人为改变 return 返回值,返回基本数据类型 字符串、数字、布尔等,不会改变return this 的值;如果返回应引用数据类型 对象 数组,那么return this 就会失效,返回你返回的结果
(7)静态方法,在方法名前面加上 static关键字
class Person{
constructor(x,y){
this.x = x;
this.y = y;
}
static aa(){
console.log(123)
}
}
console.dir(Person)
var as = new Person("pang",18)
Person.as()
类的实例化
new
class 的实例化必须通过 new 关键字。
class cont {}
let emd1 = cont();
实例化对象
class cont {
constructor(x, y) {
this.x = x;
this.y = y;
console.log('cont');
}
sum() {
return this.x + this.y;
}
}
let emd1 = new cont(2, 1);
let emd2 = new cont(3, 1);
console.log(emd1._proto_ == emd2._proto_);
emd1._proto_.sub = function() {
return this.x - this.y;
}
console.log(emd1.sub());
console.log(emd2.sub());
Class 的继承
简介
Class 可以通过extends
关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。
class Point {
}
class ColorPoint extends Point {
}
Object.getPrototypeOf()
Object.getPrototypeOf方法可以用来从子类上获取父类。因此,可以使用这个方法判断,一个类是否继承了另一个类
Object.getPrototypeOf(Dog) === Animate // true
super 关键字
super 关键字既可以当作函数使用,也可以当作对象使用。
在调用时需要注意两点:
1、子类构造函数中必须调用super方法,否则在新建对象时报错。
2、子类构造函数中必须在使用this前调用super,否则报错。
class Person
{
constructor(x, y) {
this.x = x;
this.y = y;
}
sayName(){
console.log("the name is:"+this.x);
}
}
class Worker extends Person{
constructor(x, y,job) {
//报错
}
sayJob(){
console.log("the job is:"+this.job)
}
}
super作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。
class Animate {
constructor() {
this.x = 2
this.fn = function() {
console.log('我是父类实例的方法')
}
}
num() {
console.log('我是父类的num方法')
}
}
class end extends Animate {
constructor() {
super()
}
toString() {
super.num() // 调用父类的 num() 方法
console.log(super.x)
console.log(super.fn)
console.log(this.x)
this.fn()
}
}
var end = new end()
end.toString()
类的 prototype 属性和__proto__属性
prototype是函数特有的属性,是Function的静态属性;__proto__是对象特有的属性。
因为函数本身是一种对象,所以函数既有prototype属性也有__proto__属性。
当函数使用prototype属性时,是作为构造函数使用;
当函数使用__proto__属性时,是作为一个对象使用。
另外,__proto__属性内部属性,尽量不要使用。可以用setPrototypeOf()和getPrototypeOf()代替。
class C() {}
console.log(C.prototype);
console.log(C.__proto__ === Function.prototype);
但是,在class中,prototype属性是只读的
但是,在class中,prototype属性是只读的
class A{}
class B{
add(){console.log('add')}
static add(){console.log('static add')}
}
const a = new A();
const b= new B();
console.log(Object.getOwnPropertyDescriptor(A, 'prototype'));
A.__proto__ = B;
b.add();
A.add();
A.prototype.__proto__ = B.prototype;
a.add();
原生构造函数的继承
ES6 允许继承原生构造函数定义子类,因为 ES6 是先新建父类的实例对象this
,然后再用子类的构造函数修饰this
,使得父类的所有行为都可以继承。下面是一个继承Array
的例子。
class MyArray extends Array {
constructor(...args) {
super(...args);
}
}
var arr = new MyArray();
arr[0] = 12;
arr.length
arr.length = 0;
arr[0]
Mixin 模式的实现
mixin模式就是一些提供能够被一个或者一组子类简单继承功能的类,意在重用其功能。在面向对象的语言中,我们会通过接口继承的方式来实现功能的复用。
所谓Mixin
模式,就是对象继承的一种替代方案,中文译为“混入”(mix in),意为在一个对象之中混入另外一个对象的方法。
const end = {
end() { console.log('end') }
};
class MyClass {}
Object.assign(MyClass.prototype, end);
let obj = new MyClass();
obj.end()
MyMixin
是一个混入类生成器,接受superclass
作为参数,然后返回一个继承superclass
的子类,该子类包含一个end
方法。
接着,目标类再去继承这个混入类,就达到了“混入”end
方法的目的。
class MyClass extends MyMixin(MyBaseClass) {
/* ... */
}
let c = new MyClass();
c.end();
如果需要“混入”多个方法,就生成多个混入类。
class MyClass extends Mixin1(Mixin2(MyBaseClass)) {
/* ... */
}
这种写法的一个好处,是可以调用super
,因此可以避免在“混入”过程中覆盖父类的同名方法。