第9章Class
14638 ワード
クラスメイト
私たちはjavascriptがクラスの概念がないことを知っています.ES 6は新しくクラスのキーワードを追加しました.書き込みのためにとても便利です.次にES 5とES 6を通して、ES 6という新しい文法飴を比べてみます. classとfunction; クラスと対象字面量. 静的方法「static」キーワード. 「extens」「super」を継承する. 抽象類new.targt 一.クラスと関数の関係
1.ES 5類の表現とES 6クラス
ES 5は関数コンストラクタとプロトタイプの方法によってクラスの概念をシミュレートします. class declarationsはアップグレードしません.let声明を使うように、関数宣言は自動的にアップグレードされます. は、class declarationsにおいて、すべてのコードが自動的に厳格なモードにある. classの中のすべての方法は列挙できないものです.関数宣言は方法を列挙することができなくて、Object.defineProperty方法を使う必要があります. classにはメソッド内部に「Contstruct」属性が存在しないので、newは使用できません. classコンストラクタを呼び出すにはnewを使わなければならない. classの中の方法でclass nameを書き換えることを試みて誤りを投げることができて、外部で書き直して、let声明を使った後に再び価値を賦与するように、間違いを投げることはできません; クラス文法は以下のコードに相当します.
classとfunctionの似ているところは二つの形式があります.宣言式と表現式、class式は変数宣言として一般的に使われます.あるいはパラメータ入力関数として使われます.式の形式:
4.Named Class expressions
これはNamed Function expressitionsと同じで、classの後に識別子を追加します.この識別子はclass定義の中でのみ使用できます.
1.アクセス機器get、set属性
classはコンストラクタにインスタンス属性を定義することができ、プロトタイプにアクセス属性を定義することもでき、定義方法とオブジェクトの字面量における方法は一致しています.
オブジェクトの字面の量に変数の属性を計算して、ES 6に新しく追加された文法があります.同様に、class方法とアクセス器も同様の計算命名ができます.
方法名の前に「*」を追加して、任意の方法を一つの生産器に変えてもいいです.Generator methodは対象に対してセットタイプの値であり、反復するのがとても便利です.デフォルトのディテールを定義することはSymbol.iteratorによってデフォルトのジェネレータ方法を定義できます.
クラスの本質はfunctionであり、オブジェクトとして同じパラメータまたは戻り値として扱うことができることを意味する.
1.パラメータとして
ES 6の前に、構造体に直接添加することによって、静的方法をシミュレートすることができます.
四.継承
ES 6の前に、継承を実現するのは比較的に複雑なステップであり、構造体を使って盗む必要があります.サブクラスを父親クラスの実例に向ける必要があります.(またはObject.creat()方法を見てみます.
1.ES 6の前にアナログクラスの継承は派生クラス(すなわちサブクラス)コンストラクタにsuper()を使用することができ、非派生クラスまたは一つのfunctionにsuperを使用すると、例外を投げます. は、サースにアクセスする前にsuper()を呼び出す必要があります. super()の呼び出しを唯一回避することができる方法は、オブジェクトコンストラクタからオブジェクトを返す である.
3.子類overrideの親の方法
他のプログラミング言語を学んだことがある人は、確かにoverrideを知っています.父の種類の属性を書き換えることができます.ES 6もこのような選択を提供しています.直接書き換えることができます.super.property方式も使えます.
父のクラスの静的属性は同様に継承されることができます.これはES 6の新しい概念です.
1.表現が[[Costruct]]属性と原型を持つと他の種類に継承されます.この方式はダイナミックな継承に大きな便宜を提供します.
Symbol.species:一つの静的アクセス器の属性は、一つのfunctionを返すために使用され、このfunctionは一つのコンストラクタであり、例が内部法を使用して作成しなければならない場合、下記の内蔵タイプはSymbol.species属性を持つ: Aray ArayBuffer Map Promise RegExp セット Type Aray eg:
抽象類の本質は、親がnewオペレータを使っている時に例外を出すことです.これはnew.targetを使ってコントロールできます.
クラスの出現はクラスの作成に極めて便利であり、このような構文糖は本質的にはまだfunctionであり、関数としてあるべき特性を持っています.例えば、いくつかの表現方法がfirst-citizenとしてパラメータまたは戻り値として使用できます.また、書く側と対象の字面量は十分に分かりますので、いろいろな略字を提供します.また、最も重要なのは継承の実現に非常に友好的であると同時に、mixinsは、拡張機能に大きな便宜を提供し、抽象的な出現もあります.これはjavascriptをさらにOOPにしました.
私たちはjavascriptがクラスの概念がないことを知っています.ES 6は新しくクラスのキーワードを追加しました.書き込みのためにとても便利です.次にES 5とES 6を通して、ES 6という新しい文法飴を比べてみます.
1.ES 5類の表現とES 6クラス
ES 5は関数コンストラクタとプロトタイプの方法によってクラスの概念をシミュレートします.
function Person(name, age) {
this.name = name;
this.age = age;
}
// :
// ,
Person.prototype.sayName = function() {
console.log(this.name);
}
//
var person = new Person("james", 26);
person.sayName(); // "james"
console.log(person instanceof Person); // true
ES 6はclassのキーワードを通して、constructor()の方法もあります.実例の属性をコンストラクタ関数に書いて、原型の属性は簡単な文法を使っています.class Person {
//
constructor(name, age) {
this.name = name;
this.age = age;
}
// ,
sayName() {
console.log(this.name);
}
}
// new
var person = new Person("kobe", 37);
person.sayName(); // "kobe"
// Person
console.log(typeof Person); // "function"
console.log(typeof Person.prototype.sayName); // "function"
2.クラス文法とカスタム関数表示類の違い// let ,
let PersonType = (function() {
"use strict";
// const, class
const PersonType = function(name) {
// new
if (typeof new.target === "undefined") {
throw new Error("Constructor must be called with new");
}
this.name = name;
}
//
Object.defineProperty(PersonType.prototype, "sayName", {
value: function() {
// new
if (typeof new.target !== "undefined") {
console.log(this.name)
}
},
enumerable: false,
writable: true,
configurable: true
});
return PersonType;
}());
3.Class Expressionsclassとfunctionの似ているところは二つの形式があります.宣言式と表現式、class式は変数宣言として一般的に使われます.あるいはパラメータ入力関数として使われます.式の形式:
let Person = class {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
};
機能的にはclass宣言と同じで、「name」の属性が違います.上の匿名class表現Person.nameは空の文字列です.4.Named Class expressions
これはNamed Function expressitionsと同じで、classの後に識別子を追加します.この識別子はclass定義の中でのみ使用できます.
let Person = class PersonType {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}
console.log(typeof Person); // "function"
console.log(typeof PersonType); // undefined PersonType class
相当于: let Person = (function() {
"use strict";
// const, class Person
const PersonType = function(name) {
// new
if (typeof new.target === "undefined") {
throw new Error("Constructor must be called with new");
}
this.name = name;
}
//
Object.defineProperty(PersonType.prototype, "sayName", {
value: function() {
// new
if (typeof new.target !== "undefined") {
console.log(this.name)
}
},
enumerable: false,
writable: true,
configurable: true
});
return PersonType;
}());
二.クラスと対象の字面量関係1.アクセス機器get、set属性
classはコンストラクタにインスタンス属性を定義することができ、プロトタイプにアクセス属性を定義することもでき、定義方法とオブジェクトの字面量における方法は一致しています.
class CustomHTMLElement {
constructor(element) {
this.element = element;
}
get html() {
return this.element.innerHTML;
}
set html(value) {
this.element.innerHTML = value;
}
}
var descriptor = Object.getOwnPropertyDescriptor(CustomHTMLElement.prototype, "html");
console.log("get" in descriptor); // true
console.log("set" in descriptor); // true
console.log(descriptor.enumerable); // false
jqueryを熟知しているのはhtml方法を知っているべきです.原理はこれと同じです.let CustomHTMLElement = (function() {
function CustomHTMLElement(element) {
// new
if (typeof new.target === "undefined") {
throw new Error("Constructor must be called with new");
}
this.element = element;
}
Object.defineProperty(CustomHTMLElement.prototype, "html", {
enumerable: false,
configurable: true,
get: function() {
return this.element.innerHTML;
},
set: function(value) {
this.element.innerHTML = value;
}
});
return CustomHTMLElement;
}());
2.Computed Member Namesオブジェクトの字面の量に変数の属性を計算して、ES 6に新しく追加された文法があります.同様に、class方法とアクセス器も同様の計算命名ができます.
let methodName = "sayName";
class Person {
constructor(name) {
this.name = name;
}
[methodName]() {
console.log(this.name);
}
}
アクセス:let propertyName = "html";
class CustomHTMLElement {
constructor(element) {
this.element = element;
}
get [propertyName]() {
return this.element.innerHTML;
}
set [propertyName](value) {
this.element.innerHTML = value;
}
}
3.生産方法(generatomethod)方法名の前に「*」を追加して、任意の方法を一つの生産器に変えてもいいです.Generator methodは対象に対してセットタイプの値であり、反復するのがとても便利です.デフォルトのディテールを定義することはSymbol.iteratorによってデフォルトのジェネレータ方法を定義できます.
class Collection {
constructor() {
//
this.items = [];
}
// , computed name
*[Symbol.iterator]() {
// values()
yield *this.items.values();
}
}
var c = new Collection();
c.items.push(1);
c.items.push(2);
c.items.push(3);
for (let n of c) {
console.log(n);
}
// 1
// 2
// 3
// spread
var arr = [...c];
arr; // [1, 2, 3]
4.first-citizenクラスの本質はfunctionであり、オブジェクトとして同じパラメータまたは戻り値として扱うことができることを意味する.
1.パラメータとして
function createObj(classDef) {
return new classDef();
}
let obj = createObj(class {
sayHi() {
console.log("hi");
}
});
obj.sayHi(); // "hi"
2.シングルを作成し、IIEFを利用する.let person = new class {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}("Nicholas");
person.sayName(); // "Nicholas"
三.静的方法staticES 6の前に、構造体に直接添加することによって、静的方法をシミュレートすることができます.
function PersonType(name) {
this.name = name;
}
// static method
PersonType.create = function(name) {
//
return new PersonType(name);
}
// instance method
PersonType.prototype.sayName = function() {
console.log(this.name);
}
// PersonType
var person = PersonType.create("Mike");
ES 6 staticのキーワードを導入するclass PersonType {
constructor(name) {
this.name = name;
}
// instance method
sayName() {
console.log(this.name);
}
// static method
static create(name) {
return new PersonType(name);
}
}
私達はいかなる方法に対してstaticキーワードを追加して静的な方法に変えられます.また、静的なメンバーは直接にクラスを通して、インスタンスを使ってアクセスすることができません.四.継承
ES 6の前に、継承を実現するのは比較的に複雑なステップであり、構造体を使って盗む必要があります.サブクラスを父親クラスの実例に向ける必要があります.(またはObject.creat()方法を見てみます.
1.ES 6の前にアナログクラスの継承
function Rectangle(width, height) {
this.width = width;
this.height = height;
}
Rectangle.prototype.getArea = function() {
return this.width * this.height;
}
function Square(width) {
//
Rectangle.call(this, width, width);
}
//
Square.prototype = Object.create(Rectangle.prototype, {
constructor: {
//
value: Square,
enumerable: true,
wriable: true,
configurable: true
}
});
var square = new Square(5);
square.getArea(); // 25
square instanceof Square; // true
square instanceof Rectangle; // true
2.ES 6はsuper()とextendsによって継承されます.class Rectangle {
constructor(width, height) {
this.width = width;
this.height = height;
}
getArea() {
return this.width * this.height;
}
}
class Square extends Rectangle {
constructor(width) {
// super()
super(width, width);
}
}
var square = new Square(5);
square.getArea(); // 25
square instanceof Square; // true
square instanceof Rectangle; // true
このような書き方は非常に簡潔であると同時にsuper()の注意事項を明確に使うことができます.3.子類overrideの親の方法
他のプログラミング言語を学んだことがある人は、確かにoverrideを知っています.父の種類の属性を書き換えることができます.ES 6もこのような選択を提供しています.直接書き換えることができます.super.property方式も使えます.
class Square extends Rectangle {
constructor(width) {
super(width, width);
}
// shadow getArea
getArea() {
return this.width * this.width;
}
}
またはsuperを使用するclass Square extends Rectangle {
constructor(width) {
super(width, width);
}
// override or shadow
getArea() {
return super.getArea();
}
}
4.親の静的な属性を継承する父のクラスの静的属性は同様に継承されることができます.これはES 6の新しい概念です.
class Rectangle {
constructor(width, height) {
this.width = width;
this.height = height;
}
getArea() {
return this.width * this.height;
}
//
static create(width, height) {
return new Rectangle(width, height);
}
}
class Square extends Rectangle {
constructor(width) {
super(width, width);
}
}
//
var rect = Square.create(3, 4);
console.log(rect instanceof Rectangle); // true
rect.getArea(); // 12
console.log(rect instanceof Square); // false !
5.派生クラス継承自己表現1.表現が[[Costruct]]属性と原型を持つと他の種類に継承されます.この方式はダイナミックな継承に大きな便宜を提供します.
// , [[Construct]]
function Rectangel(width, height) {
this.width = width;
this.height = height;
}
//
Rectangle.prototype.getArea = function() {
return this.widht * this,height;
}
//
class Square extends Rectangle {
constructor(width) {
super(width, width);
}
}
var x = new Square(4);
x.getArea(); // 16
x instanceof Rectangle; // true
2.ダイナミックな決定は誰から継承されますか?// , [[Construct]]
function Rectangel(width, height) {
this.width = width;
this.height = height;
}
//
Rectangle.prototype.getArea = function() {
return this.widht * this,height;
}
// , Rectangle
function getBase() {
return Rectangle;
}
// , getBase()
class Square extends getBase() {
constructor(width) {
super(width, width);
}
}
var x = new Square(4);
x.getArea(); // 16
x instanceof Rectangle; // true
3.上記の方法はmixinsを作成し、複数の属性を同じクラスに追加し、サブクラスがこのmixinsを継承するために使用できます.let serializableMixin = {
serialize() {
return JSON.stringify(this);
}
};
let AreaMixin = {
getArea() {
return this.width * this.height;
}
};
// mixins, Object.assign()
function Mixins(...mixins) {
// base
var base = function() {};
Object.assign(base.prototype, ...mixins);
return base;
}
// Mixins
class Square extends Mixins(serializableMixin, AreaMixin) {
constructor(width) {
super(width, width);
//
this.width = width;
this.height = width;
}
}
var s = new Square(3);
s.getArea(); // 9
s.serilize(); // {"width": 3, "height: 3}
4.内蔵クラス(built-in)ES 6を継承する前に内蔵クラスを継承すると問題が発生しますが、ES 6は内蔵クラス、例えばArayクラスを継承することができます.class MyArray extends Array {
// empty
}
var myArray = new MyArray();
myArray[0] = "red";
myArray.length; // 1
5.Symbol.speciesSymbol.species:一つの静的アクセス器の属性は、一つのfunctionを返すために使用され、このfunctionは一つのコンストラクタであり、例が内部法を使用して作成しなければならない場合、下記の内蔵タイプはSymbol.species属性を持つ:
class MyClass {
static get [Symbol.species]() {
return this;
}
constructor(value) {
this.value = value;
}
// ,
clone() {
return new this.constructor[Symbol.species](this.value);
}
}
//
class DerivedClass1 extends MyClass {
// empty
}
class DerivedClass2 extends MyClass {
//
static get [Symbol.species]() {
return MyClass;
}
}
let instance1 = new DerivedClass1("foo"),
clone1 = instance1.clone();
let instance2 = new DerivedClass2("bar"),
clone2 = instance2.clone();
instance1 intanceof MyClass; // true
clone1 instanceof DerivedClass1; // true
instance2 instanceof MyClass; // true
clone2 instanceof DerivedClass2; // false
例えば上記の例:class MyArray extends Array {
static get [Symbol.species]() {
return Array;
}
}
var arr = new MyArray(1,2,3,4);
var sub = arr.slice(1, 3);
sub instanceof Array; // true
sub instanceof MyArray; // false
五.抽象クラスの作成抽象類の本質は、親がnewオペレータを使っている時に例外を出すことです.これはnew.targetを使ってコントロールできます.
class Sharp {
contructor(width, height) {
// new
if (new.target === Sharp) {
throw new Error("Abstract class cannot be instantiated");
}
}
}
class Rectangle extends Sharp {
contructor(width, height) {
super();
this.width = width;
this.height = height;
}
}
var sharp = new Sharp(); // ERROR
var rec = new Rectangel(10, 5);
rec instanceof Sharp; // true
締め括りをつけるクラスの出現はクラスの作成に極めて便利であり、このような構文糖は本質的にはまだfunctionであり、関数としてあるべき特性を持っています.例えば、いくつかの表現方法がfirst-citizenとしてパラメータまたは戻り値として使用できます.また、書く側と対象の字面量は十分に分かりますので、いろいろな略字を提供します.また、最も重要なのは継承の実現に非常に友好的であると同時に、mixinsは、拡張機能に大きな便宜を提供し、抽象的な出現もあります.これはjavascriptをさらにOOPにしました.