自らes 6のclassを手に入れる
7001 ワード
新世代の標準はすでにいくつかの日を提出して、最近reactを書く時、reactは大量のclassの文法を使ってコンポーネントを書いて、classに対する理解はあまり深くなくて、そこでここでbabelから変換したコードをみんなに分かち合います.
Es 6標準のクラスは他の言語のクラスと似ていますが、これは文法糖にすぎません.底層はプロトタイプ継承によって実現されています.まず簡単なクラスの形式を見てみましょう.
コンストラクション関数とクラス内の関数を含み、プロトタイプ継承についてよく知っていれば、この形式は近似的に書くことができます.
これがクラスの雛形ですが、実際の操作は少し違います.次はbabel翻訳のes 5の文法です.
このコードに興味がある方はご覧ください.このクラスAは関数として呼び出すことができません.
このように1つのクラスをインスタンス化して、もちろんクラスはすべて継承する必要があって、新しいバージョンの中で継承はextendsで実現して、このようなクラスBがクラスAを継承することを考慮します
これは継承後のコードです
コードが長いので、見る必要はありません.ただ見るだけです.inheritsという関数は、この文から
ここでは、計算前がfalseの場合、後の式は計算されません.もちろん、falseまたは最後の値を返します.これは左から右に計算されます.superClassが存在する場合は、superClassを計算します.prototypeは、もちろん存在します.この文は、BのプロトタイプをAのprototypeをプロトタイプとするオブジェクト、つまり
ここで
すなわち、オブジェクトの
では、これまでの話を続けてみると、
このようなクラスの
newを使用してBのインスタンスbを作成すると、constructorでthisが得られる.xx、例えばthis.age this.age... など、Bのコンストラクション関数にsuper()があることを忘れてはいけません.そうしないと、Aのコンストラクション関数も実行されます.そうしないと、name属性がなく、そのオブジェクトの
新しいバージョンのクラスもプロトタイプ継承に基づいているので、基礎を築けば、新しいものに出会ってもよく理解できます.classのconstructorは以前のコンストラクション関数に対応しています.クラス全体の内容はこのコンストラクション関数のプロトタイプオブジェクトの内容です.継承に継承されたオブジェクトの内容があれば、クラス名
クラス=コンストラクション関数+プロトタイプ
Es 6標準のクラスは他の言語のクラスと似ていますが、これは文法糖にすぎません.底層はプロトタイプ継承によって実現されています.まず簡単なクラスの形式を見てみましょう.
class A {
constructor(){
this.name='xiaoming'
}
sayHello(){
console.log('hello')
}
}
コンストラクション関数とクラス内の関数を含み、プロトタイプ継承についてよく知っていれば、この形式は近似的に書くことができます.
function A(){
this.name='xiaoming';
}
A.prototype={
sayHello:function(){
console.log('hello')
}
}
これがクラスの雛形ですが、実際の操作は少し違います.次はbabel翻訳のes 5の文法です.
'use strict';
var _createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor)
descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps)
defineProperties(Constructor.prototype, protoProps);
if (staticProps)
defineProperties(Constructor, staticProps);
return Constructor;
}}();
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
var A = function () {
function A() {
_classCallCheck(this, A);
this.name = 'xiaoming';
}
_createClass(A, [{
key: 'sayHello',
value: function sayHello() {
console.log('hello');
}
}]);
return A;
}();
このコードに興味がある方はご覧ください.このクラスAは関数として呼び出すことができません.
A()
この方法で呼び出すとエラーが発生します.let a = new A();
このように1つのクラスをインスタンス化して、もちろんクラスはすべて継承する必要があって、新しいバージョンの中で継承はextendsで実現して、このようなクラスBがクラスAを継承することを考慮します
class A {
constructor(){
this.name='xiaoming'
}
sayHello(){
console.log('hello')
}
}
class B extends A{
constructor(){
super()
this.age=12
}
sayHello(){
console.log('hello')
}
}
これは継承後のコードです
'use strict';
var _createClass = function () {
function defineProperties(target, props) {
...//
}();
function _possibleConstructorReturn(self, call) { if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); }
return call && (typeof call === "object" || typeof call === "function") ? call : self;
}
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function,not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass)
Object.setPrototypeOf ?
Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
var A = function () {
function A() {
_classCallCheck(this, A);
this.name = 'xiaoming';
this.say = function () {
console.log("123");
};
}
_createClass(A, [{
key: 'sayHello',
value: function sayHello() {
console.log('hello');
}
}]);
return A;
}();
var B = function (_A) {
_inherits(B, _A);
function B() {
_classCallCheck(this, B);
var _this = _possibleConstructorReturn(this, (B.__proto__ || Object.getPrototypeOf(B)).call(this));
_this.age =12;
return _this;
}
_createClass(B, [{
key: 'sayHello',
value: function sayHello() {
console.log('hello');
}
}]);
return B;
}(A);
コードが長いので、見る必要はありません.ただ見るだけです.inheritsという関数は、この文から
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
ここでは、計算前がfalseの場合、後の式は計算されません.もちろん、falseまたは最後の値を返します.これは左から右に計算されます.superClassが存在する場合は、superClassを計算します.prototypeは、もちろん存在します.この文は、BのプロトタイプをAのprototypeをプロトタイプとするオブジェクト、つまり
B.prototype.__proto__=A.prototype
proto VS prototype
ここで
__proto__
という属性は、各オブジェクトに存在するため、オブジェクトはtoString()
のような自分の属性や方法ではない多くの属性を継承することができる.toString()
はこのオブジェクト自体の方法ではありませんが、1つのオブジェクトを呼び出すこの方法を呼び出すと、このオブジェクト自体がなく、このオブジェクトの__proto__
を探しに行き、その__proto__
が指すオブジェクトの中で探しに行き、見つからないと、この__proto__
の__proto__
の中で探し続け、これは原型チェーンを形成し、見つけるまで見つからないとエラーを報告します.prototype
と__proto__
の違いは明らかで、prototype
は関数オブジェクト特有で、彼は1つの属性として別のオブジェクト、すなわちこの関数のプロトタイプオブジェクトを指して、その存在の目的はただオブジェクトを生産するためで、この関数newを通じて出てきたオブジェクトはすべて1つの__proto__
の属性がこの関数のプロトタイプオブジェクトを指して、以下のコードから見ることができますfunction A(){
this.name='xiaoming'
}
A.prototype={
sayhi:function(){
console.log('hi')
}
}
var a=new A();
console.log(a.__proto__===A.prototype)
// true
すなわち、オブジェクトの
__proto__
属性は、そのオブジェクトを製造するコンストラクション関数のプロトタイプオブジェクトを指し、オブジェクトの字面量形式で作成されたオブジェクトの__proto__
がObject.prototype
であり、o = {};// :
o = Object.create(Object.prototype);
では、これまでの話を続けてみると、
_inherits
関数にこの言葉があります.if (superClass)
Object.setPrototypeOf ?
Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
このようなクラスの
__proto__
は親を指し,プロトタイプチェーンヘッダを親を指す,すなわちBではAのメソッドと属性を用いることができ,Bというコンストラクション関数内ではBのプロトタイプオブジェクトが以前のコードで説明されていることに注意し,Object.create
の方法でBのプロトタイプオブジェクトをAのプロトタイプにバインドし,BのプロトタイプオブジェクトはプロトタイプチェーンプロトタイプによってAを用いるプロトタイプオブジェクトの属性と方法を継承することができる.とにかく最後の状況はこうだったB.__proto__=A
B.prototype= xx
xx:{
__proto__:A.prototype
constructor:B
...
}
newを使用してBのインスタンスbを作成すると、constructorでthisが得られる.xx、例えばthis.age this.age... など、Bのコンストラクション関数にsuper()があることを忘れてはいけません.そうしないと、Aのコンストラクション関数も実行されます.そうしないと、name属性がなく、そのオブジェクトの
__proto__
をそのオブジェクトxx、つまりBというコンストラクション関数のプロトタイプオブジェクトに指向し、このプロトタイプチェーン上の属性と方法にアクセスできます.まとめ
新しいバージョンのクラスもプロトタイプ継承に基づいているので、基礎を築けば、新しいものに出会ってもよく理解できます.classのconstructorは以前のコンストラクション関数に対応しています.クラス全体の内容はこのコンストラクション関数のプロトタイプオブジェクトの内容です.継承に継承されたオブジェクトの内容があれば、クラス名
xx
で以前のコンストラクション関数を指すことができます.xx.prototype
は、プロトタイプオブジェクトを指す.新しい文法形式は、実装の詳細を外部に隠し、より簡潔に書き、不正な使用時のエラーヒントもあります.