美文网首页
9. Javascript中的类

9. Javascript中的类

作者: 莣忧草_3b53 | 来源:发表于2020-06-12 09:55 被阅读0次

9.1 ES5中的近类结构

创建一个构造函数,然后定义另一个方法并赋值给构造函数。

function Person(name) {
  this.name = name;
}
Person.prototype.sayName = function() {
  console.log(this.name)
}

var person  = new Person('Nichilas');
person.sayName(); // Nichilas

ES6中的类也是借助的这个方法

9.2 类的申明

class PersonClass {
  constructor(name) {
    this.name = name;
  }
  sayName() {
    console.log(this.name);
  }
}
let person = new PersonClass("Nicholas");
console.log(person instanceof PersonClass); // true
console.log(person instanceof Object); // true
  1. 类声明不会被提升,这与函数定义不同。存在于暂时性死区内。
  2. 类的所有方法都是不可枚举的,
  3. 严格模式
  4. 类的所有方法内部都没有 [[Construct]] ,因此使用 new 来调用它们会抛出错误。
  5. 调用类构造器时不使用 new ,会抛出错误。
  6. 在类的方法内部重写类名,会抛出错误。

9.3 类的表达式

创建单例

let person = new class {
  constructor(name) {
    this.name = name;
  }
  sayName() {
    console.log(this.name);
  }
}("Nicholas");
person.sayName(); 

需计算的成员名

9.3.1 基本的类的声明
let PersonClass = class {

}

9.4 作为一等公民的类

9.4.1 基本的类的表达式的语法
let PersonClass = class {

}
9.4.2 命名类表达式
// 具名表达式
let PersonClass = class PersonClass2 {

};
console.log(typeof PersonClass); // "function"
console.log(typeof PersonClass2); // "undefined"

9.5 访问器属性

class CustomHTMLElement {
  constructor(element) {
    this.element = element;
  }
  get html() {
    return this.element.innerHTML;
  }
  set html(value) {
    this.element.innerHTML = value;
  }
}

9.6 可计算成员名称

let methodName = "sayName";
class PersonClass {
  constructor(name) {
    this.name = name;
  }
  [methodName]() {
    console.log(this.name);
  }
}
let me = new PersonClass("Nicholas");
me.sayName(); // "Nicholas"

9.7 生成器方法

class Collection {
  constructor() {
    this.items = [];
  }
  *[Symbol.iterator]() {
    yield *this.items.values();
  }
}
var collection = new Collection();
collection.items.push(1);
collection.items.push(2);
collection.items.push(3);
for (let x of collection) {
console.log(x);
}

9.8 静态成员

ES6 的类简化了静态成员的创建,只要在方法与访问器属性的名称前添加正式的 static 标注。

class PersonClass {
  // 等价于 PersonType 构造器
  constructor(name) {
    this.name = name;
  }
  // 等价于 PersonType.prototype.sayName
  sayName() {
    console.log(this.name);
  }
  // 等价于 PersonType.create
  static create(name) {
    return new PersonClass(name);
  }
}
let person = PersonClass.create("Nicholas");

静态成员不能用实例来访问,你始终需要直接用类自身来访问它们。

9.9 继承和派生类

class Rectangle {
  constructor(length, width) {
    this.length = length;
    this.width = width;
  }
  getArea() {
    return this.length * this.width;
  }
}
class Square extends Rectangle {
  constructor(length) {
    // 与 Rectangle.call(this, length, length) 相同
    super(length, length);
  }
}
var square = new Square(3);
console.log(square.getArea()); // 9
console.log(square instanceof Square); // true
console.log(square instanceof Rectangle); // true
9.9.1 类方法的遮蔽

子类中如果有相同方法会覆盖遮蔽父类的方法

class Square extends Rectangle {
  constructor(length) {
    // 与 Rectangle.call(this, length, length) 相同
    super(length, length);
  }
  getArea() {
    return this.length*this.length
    // return super.getArea();
  }
}
9.9.2 静态成员继承

静态方法能被继承 继承过来也是静态方法

9.9.3 派生自表达式的类

只要一个表达式能够返回一个具有 [[Construct]] 属性以及原型的函数,就可以对其使用 extends 。

下列表达式类型会导致错误:1. null ;2. 生成器函数(详见第八章)

let SerializableMixin = {
  serialize() {
    return JSON.stringify(this);
  }
};
let AreaMixin = {
  getArea() {
    return this.length * this.width;
  }
};
function mixin(...mixins) {
  var base = function() {};
  Object.assign(base.prototype, ...mixins);
  return base;
}
class Square extends mixin(AreaMixin, SerializableMixin) {
  constructor(length) {
    super();
    this.length = length;
    this.width = length;
  }
}
var x = new Square(3);
9.9.4 内建对象的继承

ES6中很多内建对象可以被继承 并且保持功能 在ES5中不能保持相同功能。在 ES6 基于类的继承中, this 的值会先被基类( Array )创建,随后才被派生类的构造器( MyArray )所修改。结果是 this 初始就拥有作为基类的内置对象的所有功能,并能正确接收与之关联的所有功能。

class MyArray extends Array {
  // 代码块
}
var colors = new MyArray();
colors[0] = "red";
console.log(colors.length); // 1
colors.length = 0;
console.log(colors[0]); // undefined
9.9.5 Symbol.species属性

继承内置对象能任意能返回内置对象实例的方法,在派生类上却会自动返回派生类的实例。因此,若你拥有一个继承了 Array 的派生类 MyArray ,诸如 slice() 之类的方法都会返回 MyArray 的实例。

class MyArray extends Array {
  // 空代码块
}
let items = new MyArray(1, 2, 3, 4),
subitems = items.slice(1, 3);
console.log(items instanceof MyArray); // true
console.log(subitems instanceof MyArray); // true

Symbol.species 被用于定义一个能返回函数的静态访问器属性。每当类实例的方法(构造器除外)必须创建一个实例时,前面返回的函数就被用为新实例的构造器。

修改类的 species 是不允许的

有 Symbol.species的内置类型:
Array、ArrayBuffer 、Map、Promise、RegExp、Set、类型化数组

class MyClass {
  static get [Symbol.species]() {
    return this;
  }
  constructor(value) {
    this.value = value;
  }
  clone() {
    return new this.constructor[Symbol.species](this.value);
  }
}

class MyDerivedClass1 extends MyClass {
   // 空代码块
}

class MyDerivedClass2 extends MyClass {
  static get [Symbol.species]() {
    return MyClass;
  }
}

let instance1 = new MyDerivedClass1("foo"),
clone1 = instance1.clone(),
instance2 = new MyDerivedClass2("bar"),
clone2 = instance2.clone();

console.log(clone1 instanceof MyClass); // true
console.log(clone1 instanceof MyDerivedClass1); // true
console.log(clone2 instanceof MyClass); // true
console.log(clone2 instanceof MyDerivedClass2); // false

9.10 在类的构造函数中使用new.target

调用类时不能缺少 new ,于是 new.target 属性在类构造器内部就绝不会是
undefined

class Rectangle {
constructor(length, width) {
console.log(new.target === Rectangle);
this.length = length;
this.width = width;
}
}
// new.target 就是 Rectangle
var obj = new Rectangle(3, 4); 

相关文章

网友评论

      本文标题:9. Javascript中的类

      本文链接:https://www.haomeiwen.com/subject/kiylfhtx.html