フロントエンドの面接問題ES 5-ES 6 functionn-class実現類の違い記録の詳細
18684 ワード
ES 5の中で、私達はfunctionを通じて種類と種類の継承を実現します.ES 6の中で、classという文法飴が多くなりました.見たところ一つの種類のように見える以外に、多くの面でclassはfunctionより厳格になりました.
1.書き方
ES 5では、プロタイプとObject.create()を通じてクラスと継承を実現します.
ES 5のfunctionはアップグレードできます.以下のコードは大丈夫です.
classとlet、constは同じですので、次の2つの場合にエラーが発生します.
3.クラスの内部は厳格なモードを採用しています.
ES 5のfunctionでは、デフォルトでは非厳格モードが使われています.
ES 5のfunctionでの方法は、列挙されても良いです.
ES 5では、Function上とそのプロトタイプオブジェクト上で作成した関数には、プロトタイプのオブジェクトがありますので、newによってオブジェクトを作成することができます.
ES 5では、functionを使ってクラスをシミュレートしますが、実際には、functionはまだ関数ですので、直接関数を呼び出すことができます.
Functionについては、現在の関数のスコープ内に現在の関数名と同じ変数がない限り、現在のfunction内の変数名に直接に新しい方向を示すことができます.
8.継承が実現された時の_u u uプロト.の指向が違う
私たちはES 5でfunctionを使って相続を実現する時、prototypeの方向を変えることによって、次のようになります.
1.書き方
ES 5では、プロタイプとObject.create()を通じてクラスと継承を実現します.
function Person(){}
function Student(){}
Student.prototype = new Person()
ES 6では、class文法を使って、extensを通じてクラスと継承を実現しますが、実際の原理はやはりプロトタイプチェーンによって実現されます.class Person{}
class Student extends Person{}
2.昇格上の違いES 5のfunctionはアップグレードできます.以下のコードは大丈夫です.
var foo = new Foo()
function Foo(){
this.foo = 42
}
JavaScriptエンジンスキャンコードに変数宣言が発見された場合、変数宣言が発生した場合、varのためであれば、または宣言符がなく直接に使用された場合、またはfunctionを使用した場合、スコープの上部まで上昇します.TDZ中の変数にアクセスするとエラーが発生し、TDZから取り出すことができます.classとlet、constは同じですので、次の2つの場合にエラーが発生します.
var foo = new Foo()
class Foo{
constructor(){
this.foo = 42
}
}
// Uncaught ReferenceError: Foo is not defined
function Foo(){
this.foo = 42
}
{
var foo = new Foo()
class Foo{
constructor(){
this.foo = 42
}
}
}
// Uncaught SyntaxError: Identifier 'Foo' has already been declared
この例を挙げると、クラスとletを説明するために、constはブロックレベルのスコープの概念を持っています.ここのnew Fooはブロックレベルのスコープ外のFooを見つけられません.つまり、現在のブロックレベルのスコープの中の一時的なデッドエリアにはすでにFooがあります.3.クラスの内部は厳格なモードを採用しています.
ES 5のfunctionでは、デフォルトでは非厳格モードが使われています.
function Foo(){
foo = 42
}
ES 6のクラスでは、厳格なパターンが使われていますので、以下の表記は間違いです.class Foo{
constructor(){
fo = 42
}
}
var foo = new Foo()
// Uncaught ReferenceError: fo is not defined
4.クラスの方法は列挙できません.ES 5のfunctionでの方法は、列挙されても良いです.
function Foo(){
this.foo = 42
}
Foo.fn = function(){}
Foo.prototype.pro = function(){}
Object.keys(Foo)
// ["fn"]
Object.keys(Foo.prototype)
// ["pro"]
ES 6のクラスでの方法は、列挙されません.class Foo{
constructor(){
this.foo = 42
}
fn(){}
static sfn(){}
}
Object.keys(Foo)
// []
Object.keys(Foo.prototype)
// []
5.classの方法は原型の対象がなく、newで呼び出すことができません.ES 5では、Function上とそのプロトタイプオブジェクト上で作成した関数には、プロトタイプのオブジェクトがありますので、newによってオブジェクトを作成することができます.
function Foo(){
this.foo = 42
}
Foo.fn = function(){}
var fn = new Foo.fn()
Foo.pro = function(){}
var pro = new Foo.pro()
ただし、クラスでのアプローチは、newでオブジェクトを作成することはできません.class Foo{
constructor(){
this.foo = 42
}
static sFn(){}
fn(){}
}
var foo = new Foo()
var fn = new foo.fn()
// Uncaught TypeError: foo.fn is not a constructor
var sFn = new foo.sFn()
// Uncaught TypeError: foo.sFn is not a constructor
6.クラスはnewで呼び出す必要があります.ES 5では、functionを使ってクラスをシミュレートしますが、実際には、functionはまだ関数ですので、直接関数を呼び出すことができます.
function Foo(){
this.foo = 42
}
Foo()
classに対しては、直接に呼び出すことはできません.class Foo{
constructor(){
this.foo = 42
}
}
Foo()
// Uncaught TypeError: Class constructor Foo cannot be invoked without 'new'
7.クラス内でクラス名を書き換えられないFunctionについては、現在の関数のスコープ内に現在の関数名と同じ変数がない限り、現在のfunction内の変数名に直接に新しい方向を示すことができます.
function Foo(){
this.foo = 42
Foo = 'new Foo'
}
var f = new Foo()
console.log(Foo)
// new Foo
クラスにとっては、これは通用しません.class Foo{
constructor(){
this.foo = 42
Foo = 'new Foo'
}
}
var f = new Foo()
// Uncaught TypeError: Assignment to constant variable.
エラーの中から見られます.classはconst声明の値として評価されています.修正されてはいけません.8.継承が実現された時の_u u uプロト.の指向が違う
私たちはES 5でfunctionを使って相続を実現する時、prototypeの方向を変えることによって、次のようになります.
function Fa(){}
function Ch(){}
Ch.prototype = new Fa()
この時、Chの_u uプロト.親Faを指すのではなく、Funtion.prototypeを指しています.Ch.__proto__ === Function.prototype
// true
ES 6のクラスを使ってクラスの継承を実現する場合、__uプロト.親の類を指しますclass Fa{}
class Ch extends Fa{}
Ch.__proto__===Fa
// true
参考にES 6学習ノート(17)クラスクラスクラスクラスクラスES 5/ES 6の継承は書き方以外に何の違いがありますか?