JavaScriptはオブジェクト指向プログラミング言語ではないと人々が考える傾向があるので、JavaScriptのnew
キーワードは最初に出くわしたときにはかなり混乱を招く可能性があります。
それは5つのことをします:
this
変数が新しく作成されたオブジェクトを指すようにします。this
が指定されている場合は常に、新しく作成されたオブジェクトを使用してコンストラクタ関数を実行します。null
オブジェクト参照を返さない限り、新しく作成されたオブジェクトを返します。この場合、そのオブジェクト参照が代わりに返されます。注:コンストラクタ関数は、次のようにnew
キーワードの後の関数を表します。
new ConstructorFunction(arg1, arg2)
これが行われると、新しいオブジェクトの未定義のプロパティが要求された場合、スクリプトは代わりにプロパティのオブジェクトの[[prototype]]オブジェクトをチェックします。これがJavaScriptの伝統的なクラス継承に似たものを得る方法です。
これについて最も難しい部分は、ポイント番号2です。すべてのオブジェクト(関数を含む)は、[[[prototype]]}という内部プロパティを持ちます。 onlyは、オブジェクトの作成時に、new、Object.create、またはリテラルに基づいて設定することができます(関数のデフォルトはFunction.prototypeです。 Number.prototypeなどに番号を付けます。それはObject.getPrototypeOf(someObject)でのみ読むことができます。この値を設定または読み込む他の方法はnoです。
隠された[[[prototype]]]プロパティに加えて、関数にもprototypeという名前のプロパティがあります。あなたが作るオブジェクトのためのメソッド。
これが一例です。
ObjMaker = function() {this.a = 'first';};
// ObjMaker is just a function, there's nothing special about it that makes
// it a constructor.
ObjMaker.prototype.b = 'second';
// like all functions, ObjMaker has an accessible prototype property that
// we can alter. I just added a property called 'b' to it. Like
// all objects, ObjMaker also has an inaccessible [[prototype]] property
// that we can't do anything with
obj1 = new ObjMaker();
// 3 things just happened.
// A new, empty object was created called obj1. At first obj1 was the same
// as {}. The [[prototype]] property of obj1 was then set to the current
// object value of the ObjMaker.prototype (if ObjMaker.prototype is later
// assigned a new object value, obj1's [[prototype]] will not change, but you
// can alter the properties of ObjMaker.prototype to add to both the
// prototype and [[prototype]]). The ObjMaker function was executed, with
// obj1 in place of this... so obj1.a was set to 'first'.
obj1.a;
// returns 'first'
obj1.b;
// obj1 doesn't have a property called 'b', so JavaScript checks
// its [[prototype]]. Its [[prototype]] is the same as ObjMaker.prototype
// ObjMaker.prototype has a property called 'b' with value 'second'
// returns 'second'
これはクラス継承のようなものです。new ObjMaker()
を使用して作成したオブジェクトも 'b'プロパティを継承しているように見えるためです。
サブクラスのようなものが必要な場合は、次のようにします。
SubObjMaker = function () {};
SubObjMaker.prototype = new ObjMaker(); // note: this pattern is deprecated!
// Because we used 'new', the [[prototype]] property of SubObjMaker.prototype
// is now set to the object value of ObjMaker.prototype.
// The modern way to do this is with Object.create(), which was added in ECMAScript 5:
// SubObjMaker.prototype = Object.create(ObjMaker.prototype);
SubObjMaker.prototype.c = 'third';
obj2 = new SubObjMaker();
// [[prototype]] property of obj2 is now set to SubObjMaker.prototype
// Remember that the [[prototype]] property of SubObjMaker.prototype
// is ObjMaker.prototype. So now obj2 has a prototype chain!
// obj2 ---> SubObjMaker.prototype ---> ObjMaker.prototype
obj2.c;
// returns 'third', from SubObjMaker.prototype
obj2.b;
// returns 'second', from ObjMaker.prototype
obj2.a;
// returns 'first', from SubObjMaker.prototype, because SubObjMaker.prototype
// was created with the ObjMaker function, which assigned a for us
私は このページ を見つける前に、この問題についての大量のゴミを読みました。
この機能があるとします。
var Foo = function(){
this.A = 1;
this.B = 2;
};
このようにこれをスタンドアロン関数として呼び出すと、次のようになります。
Foo();
この関数を実行すると、window
オブジェクトに2つのプロパティ(A
とB
)が追加されます。 window
はそのように実行したときに関数を呼び出したオブジェクトであり、関数内のwindow
は関数を呼び出したオブジェクトであるため、これはthis
に追加されます。少なくともJavascriptでは。
さて、new
を使ってこのように呼びます。
var bar = new Foo();
new
を関数呼び出しに追加すると、新しいオブジェクトが作成され(ちょうどvar bar = new Object()
)、関数内のthis
が、関数を呼び出したオブジェクトではなく、作成したばかりの新しいObject
を指すようになります。そのためbar
はA
とB
のプロパティを持つオブジェクトになりました。どんな関数もコンストラクタになることができます、それはただ意味があるとは限りません。
Daniel Howardの答えに加えて、これはnew
がすることです(または少なくともそうするようです):
function New(func) {
var res = {};
if (func.prototype !== null) {
res.__proto__ = func.prototype;
}
var ret = func.apply(res, Array.prototype.slice.call(arguments, 1));
if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
return ret;
}
return res;
}
しながら
var obj = New(A, 1, 2);
と同等です
var obj = new A(1, 2);
ブラウザのコンソールで以下のコードを試してみてください。
function Foo() {
return this;
}
var a = Foo(); //returns window object
var b = new Foo(); //returns empty object of foo
a instanceof Window; // true
a instanceof Foo; // false
b instanceof Window; // false
b instanceof Foo; // true
これで コミュニティWikiの答え :)を読むことができます
だから、おそらくオブジェクトのインスタンスを作成するためのものではありません
それはまさにそのために使われています。関数コンストラクタは次のように定義します。
function Person(name) {
this.name = name;
}
var john = new Person('John');
しかしECMAScriptが持っている追加の利点はあなたが.prototype
プロパティで拡張できるということです。
Person.prototype.getName = function() { return this.name; }
このコンストラクターから作成されたすべてのオブジェクトは、アクセスできるプロトタイプチェーンのためにgetName
を持ちます。
JavaScript isはオブジェクト指向プログラミング言語で、インスタンスを作成するために使用されます。クラスベースではなくプロトタイプベースですが、それはオブジェクト指向ではないという意味ではありません。
Javascriptは、オブジェクト指向プログラミングのパラダイムをサポートする動的プログラミング言語であり、オブジェクトの新しいインスタンスを作成するために使用されます。
クラスはオブジェクトには必要ありません - Javascriptは プロトタイプベース 言語です。
いくつかの非常に良い答えが既にありますが、私はcase _ iii _ についての私の観察を強調するためにあなたがnew
ingしている関数に明示的なreturn文があるとき何が起こるかについて強調します。以下のケースを見てください。
ケースI :
var Foo = function(){
this.A = 1;
this.B = 2;
};
console.log(Foo()); //prints undefined
console.log(window.A); //prints 1
上記はFoo
が指す無名関数を呼び出す単純なケースです。この関数を呼び出すと、undefined
が返されます。明示的なreturn文がないので、JavaScriptインタプリタは関数の最後にreturn undefined;
文を強制的に挿入します。このウィンドウは、新しいthis
およびA
プロパティを取得する呼び出しオブジェクト(コンテキストB
)です。
ケースII :
var Foo = function(){
this.A = 1;
this.B = 2;
};
var bar = new Foo();
console.log(bar()); //illegal isn't pointing to a function but an object
console.log(bar.A); //prints 1
ここでnew
キーワードを見たJavaScriptインタプリタは、this
によって指される無名関数の呼び出しオブジェクト(コンテキスト上のFoo
)として機能する新しいオブジェクトを作成します。この場合、A
とB
は(ウィンドウオブジェクトの代わりに)新しく作成されたオブジェクトのプロパティになります。明示的なreturn文がないので、JavaScriptインタプリタはnew
キーワードの使用により作成された新しいオブジェクトを返すためにreturn文を強制的に挿入します。
ケースIII :
var Foo = function(){
this.A = 1;
this.B = 2;
return {C:20,D:30};
};
var bar = new Foo();
console.log(bar.C);//prints 20
console.log(bar.A); //prints undefined. bar is not pointing to the object which got created due to new keyword.
ここでも、new
キーワードを見たJavaScriptインタプリタは、this
によって指される無名関数の呼び出しオブジェクト(コンテキスト上のFoo
)として機能する新しいオブジェクトを作成します。繰り返しますが、A
およびB
は、新しく作成されたオブジェクトのプロパティになります。しかし、今回は明示的なreturn文を持っているので、JavaScriptインタプリタはnot独自のことをします。
_ iii _ の場合に注意すべきことは、new
キーワードによって作成されているオブジェクトがレーダーから失われたことです。 bar
は実際には完全に異なるオブジェクトを指していますが、これはnew
キーワードのためにJavaScriptインタープリターが作成したものではありません。
時々コードは単語より簡単です:
var func1 = function (x) { this.x = x; } // used with 'new' only
var func2 = function (x) { var z={}; z.x = x; return z; } // used both ways
func1.prototype.y = 11;
func2.prototype.y = 12;
A1 = new func1(1); // has A1.x AND A1.y
A2 = func1(1); // undefined ('this' refers to 'window')
B1 = new func2(2); // has B1.x ONLY
B2 = func2(2); // has B2.x ONLY
私にとっては、私がプロトタイプを作成していない限り、関数の内外でもう少し柔軟性があるので、func2のスタイルを使用します。
new
キーワードは、新しいオブジェクトインスタンスを作成するためのものです。そして、はい、javascriptはオブジェクト指向プログラミングパラダイムをサポートする動的プログラミング言語です。オブジェクトの命名に関する規則は、newキーワードによってインスタンス化されることになっているオブジェクトには常に大文字を使用することです。
obj = new Element();
new
キーワードは、関数が実行されているコンテキストを変更し、そのコンテキストへのポインタを返します。
new
キーワードを使用しない場合、関数Vehicle()
が実行されるコンテキストは、Vehicle
関数を呼び出すコンテキストと同じです。 this
キーワードは同じコンテキストを参照します。 new Vehicle()
を使用すると、新しいコンテキストが作成されるので、関数内のキーワードthis
は新しいコンテキストを参照します。あなたが見返りに得るのは、新しく作成されたコンテキストです。
JavaScriptは、元の仕様であるEcmaScriptを実装したものであるため、プラットフォームごとにJavaScriptが大きく異なる可能性があります。
いずれにせよ、EcmaScriptの仕様に準拠するすべてのJavaScript実装は、実装とは関係なく、オブジェクト指向言語を提供します。 ES規格によると:
ECMAScriptは、ホスト環境内で計算を実行し、計算オブジェクトを操作するためのオブジェクト指向プログラミング言語です。
JavaScriptはEcmaScriptの実装であり、したがってオブジェクト指向言語であることに同意しました。任意のオブジェクト指向言語におけるnew
操作の定義は、そのようなキーワードが特定の型のクラス(C#のような場合には匿名型を含む)からオブジェクトインスタンスを作成するために使用されると言います。
EcmaScriptでは、仕様から読み取ることができるので、クラスは使用しません。
ECMAScriptは、C++、Smalltalk、Javaなどのクラスを使用しません。代わりに、リテラル表記やオブジェクトを作成し、そのプロパティに初期値を割り当てることによってオブジェクトの全部または一部を初期化するコードを実行するコンストラクタを使用するなど、さまざまな方法でオブジェクトを作成できます。各コンストラクタは、プロトタイプベースの継承と共有プロパティの実装に使用される「prototype」という名前のプロパティを持つ関数です。オブジェクトはによって作成されます。
新しい式でコンストラクタを使用するたとえば、new Date(2009,11)は新しいDateオブジェクトを作成します。 newを使用せずにコンストラクタを呼び出すと、コンストラクタによって結果が異なります。たとえば、Date()は、オブジェクトではなく現在の日時の文字列表現を生成します。
new
キーワードは、コンストラクタとして関数を使用してオブジェクトのインスタンスを作成します。例えば:
var Foo = function() {};
Foo.prototype.bar = 'bar';
var foo = new Foo();
foo instanceof Foo; // true
インスタンスはコンストラクタ関数のprototype
から継承します。それで、上の例を与えられて...
foo.bar; // 'bar'
new
キーワードは、コンストラクタ関数からオブジェクトを作成するためにJavaScriptで使用されます。 new
キーワードはコンストラクタ関数呼び出しの前に配置する必要があり、以下のことを行います。
this
キーワードを新しく作成されたオブジェクトにバインドし、コンストラクタ関数を実行しますfunction Dog (age) {
this.age = age;
}
const doggie = new Dog(12);
console.log(doggie);
console.log(doggie.__proto__ === Dog.prototype) // true
正確にはどうなりますか:
const doggie
は言います:変数を宣言するためにメモリが必要です。=
は、この変数を=
の後の式で初期化します。new Dog(12)
です。 JSエンジンはnewキーワードを見て、新しいオブジェクトを作成し、プロトタイプをDog.prototypeに設定します。this
値を新しいオブジェクトに設定して実行されます。このステップでは、年齢が新しく作成されたドッグオブジェクトに割り当てられます。