คำหลัก 'ใหม่' ใน JavaScript คืออะไร


1744

newคำหลักใน JavaScript อาจจะค่อนข้างสับสนเมื่อมันเป็นครั้งแรกที่พบเป็นคนมักจะคิดว่า JavaScript ไม่ได้เป็นภาษาการเขียนโปรแกรมเชิงวัตถุ

  • มันคืออะไร?
  • มันแก้ปัญหาอะไรได้บ้าง?
  • มันเหมาะสมเมื่อใดและเมื่อใด

10
นอกจากนี้ยังมีเธรดที่เกี่ยวข้อง - stackoverflow.com/questions/383402/…
Chetan Sastry

อ่านตัวอย่างเหล่านี้ก่อนอื่น folks, developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
......

คำตอบ:


2144

มันทำ 5 สิ่ง:

  1. มันสร้างวัตถุใหม่ ประเภทของวัตถุนี้เป็นเพียงวัตถุ
  2. มันตั้งค่าคุณสมบัติภายในของวัตถุใหม่ที่ไม่สามารถเข้าถึงได้[[ต้นแบบ]] (เช่น__proto__ ) ให้เป็นวัตถุต้นแบบที่สามารถเข้าถึงได้ภายนอกของตัวสร้าง (ทุกฟังก์ชั่นวัตถุมีคุณสมบัติต้นแบบโดยอัตโนมัติ)
  3. มันทำให้thisจุดตัวแปรไปยังวัตถุที่สร้างขึ้นใหม่
  4. มันดำเนินการฟังก์ชั่นการสร้างโดยใช้วัตถุที่สร้างขึ้นใหม่เมื่อใดก็ตามที่thisมีการกล่าวถึง
  5. มันจะส่งกลับวัตถุที่สร้างขึ้นใหม่เว้นแต่ฟังก์ชั่นการสร้างกลับการnullอ้างอิงที่ไม่ใช่วัตถุ ในกรณีนี้การอ้างอิงวัตถุนั้นจะถูกส่งกลับแทน

หมายเหตุ: ฟังก์ชั่นคอนสตรัคหมายถึงฟังก์ชั่นหลังnewคำหลักเช่นเดียวกับใน

new ConstructorFunction(arg1, arg2)

เมื่อดำเนินการเสร็จแล้วหากมีการร้องขอคุณสมบัติที่ไม่ได้กำหนดของวัตถุใหม่สคริปต์จะตรวจสอบวัตถุ[ต้นแบบ] ของวัตถุนั้นเพื่อหาคุณสมบัติแทน นี่คือวิธีที่คุณจะได้รับสิ่งที่คล้ายกับการสืบทอดคลาสแบบดั้งเดิมใน JavaScript

ส่วนที่ยากที่สุดเกี่ยวกับเรื่องนี้เป็นจำนวนจุด 2. ทุกวัตถุ (รวมถึงฟังก์ชั่น) มีคุณสมบัติภายในที่เรียกว่า[[ต้นแบบ]] มันสามารถเพียงถูกตั้งค่าในเวลาสร้างวัตถุอย่างใดอย่างหนึ่งกับใหม่กับObject.createหรือขึ้นอยู่กับตัวอักษร (ค่าเริ่มต้นฟังก์ชั่นการ Function.prototype ตัวเลขเพื่อ Number.prototype ฯลฯ ) มันสามารถอ่านได้เฉพาะกับObject.getPrototypeOf (someObject) นอกจากนี้ไม่มีทางอื่นที่จะตั้งหรืออ่านค่านี้

ฟังก์ชั่นนอกเหนือจากคุณสมบัติ[[ต้นแบบ]] ที่ซ่อนอยู่ยังมีคุณสมบัติที่เรียกว่าแบบตัวอย่างและนี่คือสิ่งที่คุณสามารถเข้าถึงและแก้ไขเพื่อมอบคุณสมบัติและวิธีการสืบทอดสำหรับวัตถุที่คุณทำ


นี่คือตัวอย่าง:

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

ฉันอ่านขยะจำนวนหนึ่งเกี่ยวกับเรื่องนี้ก่อนที่จะหาหน้านี้ซึ่งอธิบายได้ดีมากกับไดอะแกรมที่สวยงาม


47
แค่ต้องการเพิ่ม: ในความเป็นจริงมีวิธีเข้าถึง [[ต้นแบบ] ภายใน] โดย __proto__ อย่างไรก็ตามนี่ไม่ใช่มาตรฐานและรองรับเฉพาะเบราว์เซอร์ที่ค่อนข้างใหม่ (และไม่ใช่ทั้งหมด) มีวิธีการที่เป็นมาตรฐานขึ้นมาคือ Object.getPrototypeOf (obj) แต่มันคือ Ecmascript3.1 และรองรับเฉพาะกับเบราว์เซอร์ใหม่ - อีกครั้ง ขอแนะนำโดยทั่วไปว่าไม่ควรใช้คุณสมบัตินั้น แต่สิ่งต่างๆจะมีความซับซ้อนอย่างรวดเร็วภายในนั้น
ร้องไห้สะอึกสะอื้น

9
คำถาม: จะเกิดอะไรขึ้นถ้าหากObjMakerนิยามว่าเป็นฟังก์ชันที่ส่งกลับค่า
Jim Blackler

13
@LonelyPixel newมีอยู่เพื่อให้คุณไม่ต้องเขียนวิธีการของโรงงานเพื่อสร้าง / คัดลอกฟังก์ชั่น / วัตถุ มันหมายถึง "คัดลอกสิ่งนี้ทำให้มันเหมือนกับของผู้ปกครอง 'คลาส' ทำอย่างมีประสิทธิภาพและถูกต้องและเก็บข้อมูลการสืบทอดที่สามารถเข้าถึงได้เฉพาะฉัน JS ภายใน" ในการทำเช่นนั้นมันจะแก้ไขสิ่งที่ไม่สามารถเข้าถึงได้ภายในprototypeของวัตถุใหม่เพื่อแค็ปซูลสมาชิกที่ได้รับการสืบทอดโดยเลียนแบบห่วงโซ่การสืบทอด OO แบบคลาสสิก (ซึ่งไม่สามารถแก้ไขได้) คุณสามารถจำลองสิ่งนี้ได้โดยไม่ต้องnewแต่การสืบทอดจะสามารถแก้ไขได้แบบไทม์ ดี? ไม่ดี? แล้วแต่คุณ.
วิศวกร

11
จุดเล็ก ๆ ที่จะเพิ่ม: การเรียกไปยัง constructor เมื่อนำหน้าด้วยคีย์เวิร์ดใหม่จะส่งคืนออบเจ็กต์ที่สร้างขึ้นโดยอัตโนมัติ ไม่จำเป็นต้องส่งคืนอย่างชัดเจนจากภายในตัวสร้าง
charlie roberts

7
มีข้อความที่บอกว่าNotice that this pattern is deprecated!เป็น รูปแบบที่ถูกต้องทันสมัยเพื่อตั้งค่าต้นแบบของคลาสคืออะไร
Tom Pažourek

400

สมมติว่าคุณมีฟังก์ชั่นนี้:

var Foo = function(){
  this.A = 1;
  this.B = 2;
};

หากคุณเรียกสิ่งนี้ว่าเป็นฟังก์ชั่นสแตนด์อโลน:

Foo();

การใช้งานฟังก์ชั่นนี้จะเพิ่มคุณสมบัติสองอย่างให้กับwindowวัตถุ ( AและB) มันเพิ่มเข้าไปในwindowเพราะwindowเป็นวัตถุที่เรียกว่าฟังก์ชั่นเมื่อคุณดำเนินการเช่นนั้นและthisในฟังก์ชั่นเป็นวัตถุที่เรียกว่าฟังก์ชั่น ใน Javascript อย่างน้อย

ตอนนี้เรียกมันว่าสิ่งนี้ด้วยnew:

var bar = new Foo();

เกิดอะไรขึ้นเมื่อคุณเพิ่มnewในการเรียกใช้ฟังก์ชันคือวัตถุใหม่ถูกสร้างขึ้น (แค่var bar = new Object()) และthisภายในฟังก์ชันชี้ไปที่สิ่งใหม่ที่Objectคุณเพิ่งสร้างแทนที่จะไปยังวัตถุที่เรียกว่าฟังก์ชัน ดังนั้นbarขณะนี้วัตถุที่มีคุณสมบัติและA Bฟังก์ชั่นใด ๆ สามารถเป็นตัวสร้างมันก็ไม่ได้ทำให้รู้สึก


7
ขึ้นอยู่กับบริบทการดำเนินการ ในกรณีของฉัน (การเขียนสคริปต์ Qt) เป็นเพียงวัตถุทั่วโลก
Maxmax

2
สิ่งนี้จะทำให้การใช้งานหน่วยความจำเพิ่มเติมหรือไม่
Jürgen Paul

2
เพราะ window เป็นวัตถุที่เรียกว่า function - ต้องเป็น: เพราะ window เป็นวัตถุที่มีฟังก์ชั่น
DávidHorváth

1
@Taurus ในเว็บเบราว์เซอร์ฟังก์ชั่นที่ไม่ใช่วิธีการจะเป็นวิธีการwindowโดยปริยาย แม้ในการปิดแม้ว่าจะไม่เปิดเผยชื่อ อย่างไรก็ตามในตัวอย่างมันเป็นวิธีการที่ง่ายภาวนาบนหน้าต่าง: Foo();=> =>[default context].Foo(); window.Foo();ในการแสดงออกนี้windowเป็นบริบท (ไม่เพียง แต่ผู้โทรซึ่งไม่สำคัญ)
DávidHorváth

1
@ ราศีพฤษภโดยทั่วไปใช่ อย่างไรก็ตามใน ECMA 6 และ 7 สิ่งมีความซับซ้อนมากขึ้น (ดู lambdas, คลาส, ฯลฯ )
DávidHorváth

164

นอกจากคำตอบของ 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);

73
ฉันพบว่าจาวาสคริปต์นั้นเข้าใจง่ายกว่าภาษาอังกฤษ: v
damphat

คำตอบที่ยอดเยี่ยม ฉันมีคำถามเล็ก ๆ ข้อหนึ่ง: จะเป็นfunc.prototypeไปได้nullอย่างไร? คุณช่วยอธิบายเพิ่มเติมหน่อยได้ไหม?
Tom Pažourek

6
@tomp คุณสามารถแทนที่คุณสมบัติต้นแบบได้โดยการเขียนA.prototype = null;ในกรณีnew A()นั้นจะส่งผลให้เกิดบนวัตถุนั่นคือจุดเริ่มต้นต้นแบบภายในไปยังObjectวัตถุ: jsfiddle.net/Mk42Z
basilikum

2
การตรวจสอบ typeof อาจผิดเนื่องจากวัตถุโฮสต์สามารถสร้างบางสิ่งที่แตกต่างจาก "object" หรือ "function" Object(ret) === retเพื่อทดสอบว่าสิ่งที่เป็นวัตถุที่ฉันชอบ
Oriol

2
@Oriol ขอบคุณสำหรับความคิดเห็น มันเป็นความจริงสิ่งที่คุณพูดและการทดสอบจริงใด ๆ ควรทำในลักษณะที่แข็งแกร่ง อย่างไรก็ตามฉันคิดว่าสำหรับคำตอบแนวคิดนี้การtypeofทดสอบช่วยให้เข้าใจได้ง่ายขึ้นว่าเกิดอะไรขึ้นเบื้องหลัง
basilikum

109

สำหรับผู้เริ่มต้นที่จะเข้าใจดีขึ้น

ลองใช้รหัสต่อไปนี้ในคอนโซลของเบราว์เซอร์

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 ของชุมชนได้แล้ว :)


4
คำตอบที่ดี. นอกจากนี้ - การปล่อยreturn this;ให้ผลผลิตให้ผลลัพธ์เดียวกัน
Nelu

37

ดังนั้นมันอาจไม่ใช่สำหรับการสร้างอินสแตนซ์ของวัตถุ

มันใช้ตรงนั้น คุณกำหนด constructor ของฟังก์ชันดังนี้:

function Person(name) {
    this.name = name;
}

var john = new Person('John');

อย่างไรก็ตามประโยชน์พิเศษที่ ECMAScript มีคือคุณสามารถขยายออกไปได้ด้วย.prototypeคุณสมบัติดังนั้นเราจึงสามารถทำสิ่งที่ ...

Person.prototype.getName = function() { return this.name; }

วัตถุทั้งหมดที่สร้างขึ้นจากตัวสร้างนี้จะมีgetNameห่วงโซ่ต้นแบบที่พวกเขาสามารถเข้าถึงได้


6
ฟังก์ชั่น constructors ถูกใช้เหมือนคลาสไม่มีclassคีย์เวิร์ด แต่คุณสามารถทำสิ่งเดียวกันได้
meder omuraliev

มี kindof เป็นคำหลักชั้นเรียน - ระดับสงวนไว้สำหรับการใช้งานในอนาคต
เกร็ก

11
บังเอิญที่ว่าทำไมคุณใช้ .className ไม่ .class เพื่อกำหนดคลาส CSS
เกร็ก

23
มันควรจะเป็นตัวพิมพ์ใหญ่โดยการประชุม
eomeroff

27

JavaScript เป็นภาษาการเขียนโปรแกรมเชิงวัตถุและมันถูกใช้อย่างแม่นยำสำหรับการสร้างอินสแตนซ์ มันใช้ต้นแบบมากกว่าคลาส แต่นั่นไม่ได้หมายความว่ามันไม่ใช่เชิงวัตถุ


6
ฉันอยากจะบอกว่าจาวาสคริปต์ดูเหมือนว่าจะเป็นเชิงวัตถุมากขึ้นกว่าภาษาที่ใช้ในชั้นเรียนเหล่านั้นทั้งหมด ใน JavaScript ทุกสิ่งที่คุณเขียนจะกลายเป็นออบเจกต์ทันที แต่ในภาษาที่อิงกับคลาสคุณจะต้องเขียนประกาศก่อนและหลังจากนั้นคุณจะสร้างอินสแตนซ์เฉพาะ (ออบเจ็กต์) ของคลาส และต้นแบบ JavaScript ดูเหมือนว่าจะเตือนสิ่งที่ VTABLE ทั้งหมดสำหรับภาษาที่ใช้ในห้องเรียน
JustAMartin

14

Javascript เป็นภาษาการเขียนโปรแกรมแบบไดนามิกที่รองรับกระบวนทัศน์การเขียนโปรแกรมเชิงวัตถุและใช้สำหรับการสร้างอินสแตนซ์ใหม่ของวัตถุ

คลาสไม่จำเป็นสำหรับวัตถุ - Javascript เป็นภาษาที่ใช้ต้นแบบ


12

มีคำตอบที่ดีมากอยู่แล้ว แต่ฉันกำลังโพสต์คำตอบใหม่เพื่อเน้นการสังเกตของฉันในกรณีที่IIIด้านล่างเกี่ยวกับสิ่งที่เกิดขึ้นเมื่อคุณมีคำสั่งส่งคืนอย่างชัดเจนในฟังก์ชันที่คุณกำลังnewทำอยู่ ดูกรณีด้านล่าง:

กรณี I :

var Foo = function(){
  this.A = 1; 
  this.B = 2;
};
console.log(Foo()); //prints undefined
console.log(window.A); //prints 1

Fooดังกล่าวข้างต้นเป็นกรณีธรรมดาของการเรียกฟังก์ชั่นที่ไม่ระบุชื่อโดยชี้ให้เห็น เมื่อคุณเรียกใช้ฟังก์ชั่นนี้มันจะกลับundefinedมา เนื่องจากไม่มีคำสั่งส่งคืนที่ชัดเจนดังนั้นล่าม JavaScript จึงใส่return undefined;คำสั่งลงในส่วนท้ายของฟังก์ชัน หน้าต่างที่นี่คือวัตถุที่เรียกใช้ (ตามบริบทthis) ซึ่งรับค่าใหม่AและBคุณสมบัติ

กรณีที่สอง :

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

นี่ JavaScript ล่ามเห็นnewคำหลักที่สร้างวัตถุใหม่ซึ่งทำหน้าที่เป็นวัตถุภาวนา (บริบทthis) Fooของฟังก์ชั่นที่ไม่ระบุชื่อโดยชี้ให้เห็น ในกรณีนี้AและBกลายเป็นคุณสมบัติบนวัตถุที่สร้างขึ้นใหม่ (แทนที่วัตถุหน้าต่าง) เนื่องจากคุณไม่มีคำสั่งส่งคืนที่ชัดเจนดังนั้นล่าม JavaScript จึงใส่คำสั่ง return เพื่อส่งคืนออบเจ็กต์ใหม่ที่สร้างขึ้นเนื่องจากการใช้newคำหลัก

กรณีที่สาม :

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.

ที่นี่อีกครั้ง JavaScript ล่ามเห็นnewคำหลักที่สร้างวัตถุใหม่ซึ่งทำหน้าที่เป็นวัตถุภาวนา (บริบทthis) Fooของฟังก์ชั่นที่ไม่ระบุชื่อโดยชี้ให้เห็น อีกครั้งAและBกลายเป็นคุณสมบัติในวัตถุที่สร้างขึ้นใหม่ แต่คราวนี้คุณมีคำสั่งส่งคืนอย่างชัดเจนดังนั้นล่าม JavaScript จะไม่ทำสิ่งใดของมันเอง

สิ่งที่ควรทราบในกรณีที่IIIคือวัตถุที่สร้างขึ้นเนื่องจากnewคำหลักหายไปจากเรดาร์ของคุณ barจริง ๆ แล้วชี้ไปที่วัตถุที่แตกต่างอย่างสิ้นเชิงซึ่งไม่ใช่ล่าม JavaScript ที่สร้างขึ้นเนื่องจากnewคำหลัก

อ้างถึง David Flanagan จาก JavaScripit: The Definitive Guide (6th Edition), Ch. 4, หน้า # 62:

เมื่อนิพจน์การสร้างวัตถุได้รับการประเมิน JavaScript จะสร้างวัตถุว่างเปล่าใหม่เช่นเดียวกับที่สร้างขึ้นโดย object initializer {} ถัดไปจะเรียกใช้ฟังก์ชันที่ระบุพร้อมกับอาร์กิวเมนต์ที่ระบุส่งผ่านวัตถุใหม่เป็นค่าของคำหลักนี้ ฟังก์ชันสามารถใช้ฟังก์ชันนี้เพื่อเริ่มต้นคุณสมบัติของวัตถุที่สร้างขึ้นใหม่ ฟังก์ชั่นที่เขียนขึ้นเพื่อใช้เป็นคอนสตรัคเตอร์จะไม่ส่งคืนค่าและค่าของนิพจน์การสร้างวัตถุเป็นวัตถุที่สร้างขึ้นใหม่และเริ่มต้นได้ หากตัวสร้างส่งคืนค่าวัตถุค่านั้นจะกลายเป็นค่าของนิพจน์การสร้างวัตถุและวัตถุที่สร้างขึ้นใหม่จะถูกทิ้ง

--- ข้อมูลเพิ่มเติม ---

ฟังก์ชั่นที่ใช้ในตัวอย่างโค้ดของกรณีข้างต้นมีชื่อพิเศษใน JS world ดังต่อไปนี้:

Case I และ II - ฟังก์ชันตัวสร้าง

Case III - ฟังก์ชั่นจากโรงงาน ไม่ควรใช้ฟังก์ชั่นจากโรงงานกับnewคำหลักที่ฉันได้ทำเพื่ออธิบายแนวคิดในเธรดปัจจุบัน

คุณสามารถอ่านเกี่ยวกับความแตกต่างระหว่างพวกเขาในนี้ด้าย


กรณีของคุณ 3 เป็น gr8 สังเกต
Appu

5

บางครั้งรหัสง่ายกว่าคำ:

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 เพราะให้ความยืดหยุ่นเล็กน้อยทั้งภายในและภายนอกฟังก์ชั่น


3
B1 = new func2(2); <- ทำไมจะไม่ได้B1.y ?
sunny_dev

@sunny_dev ฉันไม่ใช่ผู้เชี่ยวชาญ JS แต่อาจเป็นเพราะfunc2ส่งคืนค่าโดยตรง (วัตถุ z) แทนที่จะทำงาน / ส่งคืนด้วยค่าภายใน (นี่)
Eagle

5

newคำหลักที่เปลี่ยนแปลงบริบทตามที่ฟังก์ชั่นจะถูกเรียกใช้และกลับชี้ไปที่บริบท

เมื่อคุณไม่ใช้newคำสำคัญบริบทภายใต้ฟังก์ชันที่Vehicle()ทำงานจะเป็นบริบทเดียวกันกับที่คุณเรียกใช้Vehicleฟังก์ชัน thisคำหลักจะอ้างถึงบริบทเดียวกัน เมื่อคุณใช้new Vehicle()บริบทใหม่จะถูกสร้างขึ้นดังนั้นคำหลักthisภายในฟังก์ชั่นหมายถึงบริบทใหม่ สิ่งที่คุณจะได้รับคือบริบทที่สร้างขึ้นใหม่


นั่นเป็นคำตอบที่ลึกซึ้งมากในแง่ของขอบเขต นอกจากนี้คำตอบของ Gr8
appu

3

newคำหลักสำหรับการสร้างอินสแตนซ์วัตถุใหม่ และใช่จาวาสคริปต์เป็นภาษาการเขียนโปรแกรมแบบไดนามิกซึ่งรองรับกระบวนทัศน์การเขียนโปรแกรมเชิงวัตถุ ข้อตกลงเกี่ยวกับการตั้งชื่อวัตถุนั้นให้ใช้ตัวพิมพ์ใหญ่สำหรับวัตถุที่ควรจะสร้างอินสแตนซ์โดยคำหลักใหม่

obj = new Element();

2

สรุป:

newคำหลักที่ใช้ในจาวาสคริปต์เพื่อสร้างวัตถุจากฟังก์ชั่นผู้สร้าง newคำหลักที่จะต้องมีการวางไว้ก่อนการเรียกฟังก์ชั่นคอนสตรัคและจะทำสิ่งต่อไปนี้:

  1. สร้างวัตถุใหม่
  2. ตั้งค่าต้นแบบของวัตถุนี้เป็นคุณสมบัติต้นแบบของฟังก์ชันตัวสร้าง
  3. ผูกthisคำหลักกับวัตถุที่สร้างขึ้นใหม่และดำเนินการฟังก์ชั่นการสร้าง
  4. ส่งคืนวัตถุที่สร้างขึ้นใหม่

ตัวอย่าง:

function Dog (age) {
  this.age = age;
}

const doggie = new Dog(12);

console.log(doggie);
console.log(doggie.__proto__ === Dog.prototype) // true

เกิดอะไรขึ้น:

  1. const doggie พูดว่า: เราต้องการหน่วยความจำสำหรับการประกาศตัวแปร
  2. โอเปอเรเตอร์ assigment =พูดว่า: เราจะเริ่มต้นตัวแปรนี้ด้วยนิพจน์หลังจาก=
  3. new Dog(12)การแสดงออกเป็น เอ็นจิน JS เห็นคำสำคัญใหม่สร้างวัตถุใหม่และตั้งค่าต้นแบบเป็น Dog.prototype
  4. ฟังก์ชั่นคอนสตรัคจะดำเนินการกับการthisตั้งค่าเป็นวัตถุใหม่ ในขั้นตอนนี้คือที่อายุถูกกำหนดให้กับวัตถุ doggie ที่สร้างขึ้นใหม่
  5. วัตถุที่สร้างขึ้นใหม่จะถูกส่งกลับและกำหนดให้กับตัวแปรสุนัข

1

newคำหลักที่สร้างอินสแตนซ์ของวัตถุที่ใช้ทำหน้าที่เป็นผู้สร้าง ตัวอย่างเช่น

var Foo = function() {};
Foo.prototype.bar = 'bar';

var foo = new Foo();
foo instanceof Foo; // true

อินสแตนซ์รับช่วงจากprototypeฟังก์ชันของตัวสร้าง ได้รับตัวอย่างข้างต้น ...

foo.bar; // 'bar'

2
คำหลักใหม่จะเชื่อมโยงฟังก์ชั่นเป็นผู้สร้างอยู่แล้ว คุณไม่จำเป็นต้องคืนสิ่งใดเลย คุณสามารถทำได้: function foo (x) {this.bar = x; } var obj = foo ใหม่ (10); การแจ้งเตือน (obj.bar);
reko_t

คุณไม่จำเป็นต้องส่งคืนออบเจ็กต์จากฟังก์ชั่นคอนสตรัคเตอร์เว้นแต่คุณจะต้องการเพื่อวัตถุประสงค์เฉพาะ ตัวอย่างเช่นถ้าคุณต้องส่งคืนอินสแตนซ์ของวัตถุที่เฉพาะเจาะจงแทนที่จะสร้างวัตถุใหม่ทุกครั้ง (ไม่ว่าจะด้วยเหตุผลใดก็ตาม) อย่างไรก็ตามในตัวอย่างของคุณไม่จำเป็นเลย
Chetan Sastry

มันเป็นตัวอย่าง คุณสามารถคืนวัตถุได้ มีหลายรูปแบบที่ใช้ในสถานการณ์นี้ฉันให้รูปแบบหนึ่งเป็น "ตัวอย่าง" ดังนั้นคำของฉัน "เช่น"
เปลือกตา

1

จาวาสคริปต์ต่อ Si สามารถแตกต่างกันอย่างมากจากแพลตฟอร์มไปยังแพลตฟอร์มเนื่องจากมันเป็นการใช้งานของข้อกำหนดดั้งเดิม EcmaScript

ไม่ว่าในกรณีใดการใช้งาน JavaScript ทั้งหมดที่เป็นไปตามข้อกำหนดของ EcmaScript นั้นจะให้ภาษาเชิงวัตถุแก่คุณ ตามมาตรฐาน ES:

ECMAScript เป็นภาษาโปรแกรมเชิงวัตถุสำหรับดำเนินการคำนวณและจัดการวัตถุคำนวณภายในสภาพแวดล้อมโฮสต์

ตอนนี้เราได้ตกลงกันแล้วว่า JavaScript คือการนำ EcmaScript มาใช้ดังนั้นมันจึงเป็นภาษาเชิงวัตถุ คำจำกัดความของการnewดำเนินการในภาษาเชิงวัตถุใด ๆ กล่าวว่าคำหลักดังกล่าวถูกใช้เพื่อสร้างอินสแตนซ์ของวัตถุจากคลาสบางประเภท (รวมถึงประเภทที่ไม่ระบุชื่อในกรณีเช่น C #)

ใน EcmaScript เราไม่ใช้คลาสอย่างที่คุณสามารถอ่านได้จากสเปค:

ECMAScript ไม่ได้ใช้คลาสเช่นที่อยู่ใน C ++, Smalltalk หรือ Java วัตถุอาจถูกสร้างขึ้นด้วยวิธีการต่าง ๆ รวมถึงผ่านสัญกรณ์ตามตัวอักษรหรือผ่านตัวสร้างที่สร้างวัตถุแล้วรันโค้ดที่เริ่มต้นทั้งหมดหรือบางส่วนโดยการกำหนดค่าเริ่มต้นให้กับคุณสมบัติของพวกเขา ตัวสร้างแต่ละตัวเป็นฟังก์ชั่นที่มีคุณสมบัติชื่อว่า - prototype ‖ที่ใช้ในการสร้างการสืบทอดที่อิงกับต้นแบบและคุณสมบัติที่ใช้ร่วมกัน วัตถุถูกสร้างขึ้นโดย
ใช้ constructors ในนิพจน์ใหม่ ตัวอย่างเช่นใหม่ Date (2009,11) สร้างวัตถุ Date ใหม่ การเรียกคอนสตรัคเตอร์โดยไม่ใช้ใหม่จะมีผลกระทบที่ขึ้นอยู่กับคอนสตรัคเตอร์ ตัวอย่างเช่น Date () สร้างการแสดงสตริงของวันที่และเวลาปัจจุบันแทนที่จะเป็นวัตถุ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.