《understanding ESMAScript 6》之类 ( introducting javascript classes)

阅读: 评论:0

《understanding ESMAScript 6》之类 ( introducting javascript classes)

《understanding ESMAScript 6》之类 ( introducting javascript classes)

类 introducing javascript classes

es5 中的类结构 class-like structures in ecmascript5

// 创建一个构造函数
function PersonType(name) {this.name = name;
}// 在构造函数的原型上添加方法
PersonType.prototype.sayName = function() {console.log(this.name);
};// 创建一个PersonType的实例person
let person = new PersonType("kk");// 沿着原型链向上查找,直到找到sayName方法
person.sayName(); // 输出 kkconsole.log(person instanceof personType); // true
console.log(person instanceof Object); // true

类声明 class declarations

一个基本的类声明 a basic class declaration
class PersonClass {// 构造函数constructor(name) {this.name = name;}sayName() {console.log(this.name);}
}let person = new PersonClass("kk");person.sayName(); // 输出 kkconsole.log(person instanceof PersonClass); // true
console.log(person instanceof Object); // trueconsole.log(typeof PersonClass); // function
console.log(typeof PersonClass.prototype.sayName); // function
为何使用类声明 why use the class syntax
  1. 类声明和函数不同,他们是不会被提升的,当执行流作用到类声明之前类会存在于暂存性死区中。
  2. 类声明的代码自动运行在严格模式下,同时没有任何办法可以手动的切换到非严格模式下。
  3. 类的所有方法都是不可枚举的。
  4. 不能再类的内部重写类名。

所以,PersonClass 声明等同如下未使用类语法的代码:

// 完全等效于PersonClass
let PersonType2 = function() {
  "use strict";const PersonType2 = function(name) {// 确定方法是被new调用的if (typeof new.target === "undefined") {throw new Error("Constructor must be called with new.");}this.name = name;};Object.defineProperties(PersonType2.prototype, "sayName", {value: function() {// 检查new.target以确保类是由new来调用的。if (typeof new.target === "undefined") {throw new Error("Constructor must be called with new.");}console.log(this.name);},writable: true,configurable: true,enumerable: false});return PersonType2;
};

类表达式 class expressions

类和函数都有两种存在形式:声明和表达式。

一个基本的类表达式 basic class expression
// anonymous class expressions
let PersonClass = class {constructor(name) {this.name = name;}// ....
};console.log(PersonClass.name); // ''
具名表达式 named class expressions
let PersonClass = class PersonClass1 {constructor(name) {this.name = name;}// 相当于// const PersonClass1 = function (name) {//   if(typeof new.target == 'undefined'){//     throw new Error('err');//   }//   this.name = name;// }// return PersonClass1;
};

再来看一种现象:

console.log(typeof PersonClass1); // "undefined"
/*** 原因: PersonClass1只能在类的内部使用,外部是访问不到的*/

总结:在该匿名类表达式中,PersonClass.name 是个空的字符串。如果使用了类声明,那么 PersonClass.name 的值为 “PersonClass”。

注:译者在这里测试发现 Edge,Chrome 及 Opera 的匿名表达式都会返回类名,只有 FireFox 返回空字符串

一等公民,一等类

在编程中,如果某些东西能够作为值使用,那么他被成为一等公民。js 中的函数就是一等公民。又叫做一等函数。

// 使用 1. 作为参数function createObj(classDef) {return new classDef();
}
let obj = createObj(class {sayHi() {console.log("hi");}}
);obj.sayHi(); // 'hi'
// 2. 立即执行
let person = new class {constructor(name) {this.name = name;}sayName() {console.log(this === person); // trueconsole.log(this.name);}
}("kk");person.sayName(); // 'kk'

访问器属性 accessor properties

class CreateHtmlElement {constructor(ele) {this.ele = ele;}get html() {return this.ele.innerHtml;}set html(value) {this.ele.innerHtml = value;}
}let descriptor = OwnPropertyDescriptor(CreateHtmlElement.prototype,"html"
);console.log("get" in descriptor); // true
console.log("set" in descriptor); // true
console.umerable); // false

如果不使用类的写法,感受一下 完全等效于 CreateHtmlElement

let CreateHtmlElement = (function() {
  "use strict";const CreateHtmlElement = function(ele) {if (new.target == "undefined") {throw new Error("err!");}this.ele = ele;};OwnPropertyDescriptor(CreateHtmlElement.prototype, "html", {writable: true,configurable: true,enumerable: false,get: function() {return this.ele.innerHtml;},set: function(value) {this.ele.innerHtml = value;}});return CreateHtmlElement;
})();

动态命名 computed member names

// 例子1  动态命名方法
let className = "sayname";class PersonClass {constructor(name) {this.name = name;}[className]() {console.log(this.name);}
}let person = new PersonClass("jj");
person.sayName(); // 'jj'
// 例子2 动态命名属性
let animalName = "animalName";
class Animal {constructor(animalKind) {this.animalKind = animalKind;}set [animalName](name) {this.animalKind.animalName = name;}get [animalName]() {return this.animalKind.animalName;}
}let dog = new Animal("dog");
dog.set("huahua");
(); // 'huahua'

生成器方法 generator methods

该方法返回了一个经过硬编码的迭代器,当你想要一个具有集合性质的对象并能轻松迭代包含值得时候,生成器方法相当有用。

class MyClass {*createIterator() {yield 1;yield 2;yield 3;}
}let myclass = new MyClass();let iterator = ateIterator();for (const i of iterator) {console.log(i);
}
// 依次输出1 2 3
设置类的默认迭代器

通过给类的 Symbol.iterator 定义一个生成器方法来设置类的默认迭代器。

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);
}// 输出:
// 1
// 2
// 3

静态成员 static members

es5 中的实现:

function PersonType(name) {this.name = name;
}// 静态方法 create
ate = function(name) {return new PersonType(name);
};// 实例方法 sayName
PersonType.prototype.sayName = function() {console.log(this.name);
};var person = ate("Nicholas");

es6 中的实现:

class PersonClass {// 等效于 PersonType 构造函数constructor(name) {this.name = name;}// 等效于 PersonType.prototype.sayNamesayName() {console.log(this.name);}// 等效于 atestatic create(name) {return new PersonClass(name);}
}let person = ate("Nicholas");

静态成员不能被实例访问。你必须通过类本身来使用它们。

类的继承

es5 中的实现:

function Rectangle(length, width) {this.length = length;this.width = width;
}Area = function() {return this.length * this.width;
};function Square(length) {Rectangle.call(this, length, length);
}Square.prototype = ate(Rectangle.prototype, {constructor: {value: Square,enumerable: true,writable: true,configurable: true}
});var square = new Square(3);console.Area()); // 9
console.log(square instanceof Square); // true
console.log(square instanceof Rectangle); // true

es6 中的实现:

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.Area()); // 9
console.log(square instanceof Square); // true
console.log(square instanceof Rectangle); // true
派生类使用父类的静态方法
class A {constructor(width, height) {this.width = width;this.height = height;}getArea() {return this.width * this.height;}// 静态成员 静态方法static create(width, height) {return width * height;}
}class B extends A {constructor(length) {// 使用super和指定的参数来调用A的构造函数super(length, length);}getArea() {// 调用父类中的方法 使用super.方法名Area();}
}
let b = new B(3);
b.getArea(); // 9// 派生类可以使用父类的静态方法
B.create(2, 3); // 6

注意: 只有派生类本身可以使用他的静态方法,派生类的实例不可以使用

本文发布于:2024-02-04 04:54:45,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170699515952239.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23