ตัวสร้างในวัตถุ JavaScript


402

คลาส / วัตถุ JavaScript สามารถมีโครงสร้างได้หรือไม่? พวกเขาเป็นอย่างไรบ้าง



คำตอบ:


408

ใช้ต้นแบบ:

function Box(color) // Constructor
{
    this.color = color;
}

Box.prototype.getColor = function()
{
    return this.color;
};

การซ่อน "สี" (ค่อนข้างคล้ายกับตัวแปรสมาชิกส่วนตัว):

function Box(col)
{
   var color = col;

   this.getColor = function()
   {
       return color;
   };
}

การใช้งาน:

var blueBox = new Box("blue");
alert(blueBox.getColor()); // will alert blue

var greenBox = new Box("green");
alert(greenBox.getColor()); // will alert green

3
@ BorisB ใช่คุณทำเช่นนี้จะกำหนดสีและ getColor บนกล่องวัตถุมิฉะนั้นคุณจะกำหนดตัวแปรในขอบเขตปกติ
Nick

4
@Jeach ใช่มันเป็นเช่นนั้น ฉันได้ให้ตัวอย่างข้อมูลอื่นที่ซ่อนcolorไว้ ฉันขอแนะนำให้คุณใช้ส่วนใหญ่ตามความชอบส่วนบุคคล (การป้องกันและความเรียบง่าย)
Nick

6
@CamiloMartin แม้ว่าจะไม่จำเป็นเสมอไปการสร้างตัวแปร "ส่วนตัว" (หรือในกรณีนี้ไม่สามารถตั้งชื่อได้) อาจเป็นวิธีที่มีประโยชน์ในการป้องกันไม่ให้รหัสภายนอกขึ้นอยู่กับรายละเอียดการใช้งานในชั้นเรียนของคุณ แม้เพียงแค่การบ่งชี้ว่าองค์ประกอบของชั้นเรียนเป็นสาธารณะ / ส่วนตัวสามารถเป็นประโยชน์กับผู้ใช้ภายนอก
Nick

49
varทำให้ตัวแปรส่วนตัว thisทำให้เป็นตัวแปรสาธารณะ
EhevuTov

3
@AlanKis (อย่างน้อยในบางกลไก Javascript) การติดตามสแต็กจะอยู่ในกรณีฟังก์ชันที่ไม่ระบุชื่อซึ่งไม่ได้พูดถึงFooในขณะที่ในกรณีหลังจะรู้ว่ามันFooถูกเรียกใช้ มีประโยชน์มากสำหรับการแก้ไขข้อบกพร่อง
Joachim Isaksson

248

นี่คือเทมเพลตที่บางครั้งฉันใช้สำหรับพฤติกรรมที่คล้ายกันของ OOP ใน JavaScript อย่างที่คุณเห็นคุณสามารถจำลองสมาชิกส่วนตัว (ทั้งแบบคงที่และอินสแตนซ์) โดยใช้การปิด สิ่งที่new MyClass()จะส่งคืนคือวัตถุที่มีคุณสมบัติที่กำหนดให้กับthisวัตถุและในprototypeวัตถุของ "คลาส" เท่านั้น

var MyClass = (function () {
    // private static
    var nextId = 1;

    // constructor
    var cls = function () {
        // private
        var id = nextId++;
        var name = 'Unknown';

        // public (this instance only)
        this.get_id = function () { return id; };

        this.get_name = function () { return name; };
        this.set_name = function (value) {
            if (typeof value != 'string')
                throw 'Name must be a string';
            if (value.length < 2 || value.length > 20)
                throw 'Name must be 2-20 characters long.';
            name = value;
        };
    };

    // public static
    cls.get_nextId = function () {
        return nextId;
    };

    // public (shared across instances)
    cls.prototype = {
        announce: function () {
            alert('Hi there! My id is ' + this.get_id() + ' and my name is "' + this.get_name() + '"!\r\n' +
                  'The next fellow\'s id will be ' + MyClass.get_nextId() + '!');
        }
    };

    return cls;
})();

ฉันถูกถามเกี่ยวกับการสืบทอดโดยใช้รูปแบบนี้ดังนั้นไปที่นี่:

// It's a good idea to have a utility class to wire up inheritance.
function inherit(cls, superCls) {
    // We use an intermediary empty constructor to create an
    // inheritance chain, because using the super class' constructor
    // might have side effects.
    var construct = function () {};
    construct.prototype = superCls.prototype;
    cls.prototype = new construct;
    cls.prototype.constructor = cls;
    cls.super = superCls;
}

var MyChildClass = (function () {
    // constructor
    var cls = function (surName) {
        // Call super constructor on this instance (any arguments
        // to the constructor would go after "this" in call(…)).
        this.constructor.super.call(this);

        // Shadowing instance properties is a little bit less
        // intuitive, but can be done:
        var getName = this.get_name;

        // public (this instance only)
        this.get_name = function () {
            return getName.call(this) + ' ' + surName;
        };
    };
    inherit(cls, MyClass); // <-- important!

    return cls;
})();

และตัวอย่างการใช้งานทั้งหมด:

var bob = new MyClass();
bob.set_name('Bob');
bob.announce(); // id is 1, name shows as "Bob"

var john = new MyChildClass('Doe');
john.set_name('John');
john.announce(); // id is 2, name shows as "John Doe"

alert(john instanceof MyClass); // true

ที่คุณสามารถดูชั้นเรียนได้อย่างถูกต้องโต้ตอบกับแต่ละอื่น ๆ (พวกเขาแชร์รหัสคงที่จากMyClassที่announceวิธีการใช้ที่ถูกต้องget_nameวิธีการอื่น ๆ )

สิ่งหนึ่งที่ควรทราบคือความต้องการคุณสมบัติอินสแตนซ์เงา คุณสามารถทำให้inheritฟังก์ชั่นผ่านคุณสมบัติของอินสแตนซ์ทั้งหมด (โดยใช้hasOwnProperty) ที่เป็นฟังก์ชั่นและเพิ่มsuper_<method name>คุณสมบัติโดยอัตโนมัติ นี้จะช่วยให้คุณเรียกแทนการเก็บไว้ในค่าชั่วคราวและเรียกมันผูกไว้ใช้this.super_get_name()call

สำหรับวิธีการในต้นแบบคุณไม่จำเป็นต้องกังวลเกี่ยวกับข้างต้น แต่ถ้าคุณต้องการเข้าถึงวิธีต้นแบบระดับสูงคุณสามารถโทรthis.constructor.super.prototype.methodNameได้ ถ้าคุณต้องการทำให้มันละเอียดน้อยคุณสามารถเพิ่มคุณสมบัติความสะดวกสบายได้แน่นอน :)


7
เพียงแค่ทราบเกี่ยวกับcls.prototypeส่วน: "ใช้ร่วมกันข้ามอินสแตนซ์" เป็นเพียงการอ่านค่า (โทรannounce) ถ้าคุณตั้งค่าmyClassInstance.announceเป็นค่าอื่นมันจะสร้างคุณสมบัติใหม่myClassInstanceดังนั้นจึงจะใช้กับวัตถุนั้นไม่ใช่อินสแตนซ์อื่นของคลาส การกำหนดให้MyClass.prototype.announceจะมีผลกับอินสแตนซ์ทั้งหมดแม้ว่า
Matthew Crumley

1
ไม่มีปัญหายินดีให้ความช่วยเหลือ! :)
Blixt

2
ขอบคุณ! ชอบมาก! คุณสามารถแสดงตัวอย่างของการสืบทอดคลาสในวิธีนี้ได้ไหม
Dmitrij Golubev

2
@DmitrijGolubev, Brad Dwyer และ Nathan C. Tresch: ฉันได้เพิ่มการถ่ายทอดทางพันธุกรรม แต่มันค่อนข้างซับซ้อนดังนั้นฉันมักจะแนะนำให้คุณแก้ปัญหาที่ง่ายกว่าเว้นแต่คุณจะต้องมีการถ่ายทอดทางเพศใน JavaScript (ซึ่งจริงๆแล้วเป็นเพียง ภาษาต้นแบบ)
Blixt

1
@guiomie มันเป็นวิธี "คงที่สาธารณะ" ดังนั้นคุณจะเรียกมันในฟังก์ชั่นคอนสตรัค ("คลาส") ไม่ใช่ตัวอย่าง:MyClass.get_nextId()
Blixt

166

มันดูเหมือนว่าฉันมากที่สุดของคุณจะให้ตัวอย่างของ getters และ setters ไม่นวกรรมิกคือhttp://en.wikipedia.org/wiki/Constructor_(object-oriented_programming)

lunched-dan ใกล้เคียง แต่ตัวอย่างไม่ทำงานใน jsFiddle

ตัวอย่างนี้สร้างฟังก์ชันตัวสร้างส่วนตัวที่ทำงานเฉพาะในระหว่างการสร้างวัตถุ

var color = 'black';

function Box()
{
   // private property
   var color = '';

   // private constructor 
   var __construct = function() {
       alert("Object Created.");
       color = 'green';
   }()

   // getter
   this.getColor = function() {
       return color;
   }

   // setter
   this.setColor = function(data) {
       color = data;
   }

}

var b = new Box();

alert(b.getColor()); // should be green

b.setColor('orange');

alert(b.getColor()); // should be orange

alert(color); // should be black

หากคุณต้องการที่จะกำหนดคุณสมบัติสาธารณะแล้วคอนสตรัคสามารถกำหนดเช่น:

var color = 'black';

function Box()
{
   // public property
   this.color = '';

   // private constructor 
   var __construct = function(that) {
       alert("Object Created.");
       that.color = 'green';
   }(this)

   // getter
   this.getColor = function() {
       return this.color;
   }

   // setter
   this.setColor = function(color) {
       this.color = color;
   }

}

var b = new Box();

alert(b.getColor()); // should be green

b.setColor('orange'); 

alert(b.getColor()); // should be orange

alert(color); // should be black

45
นี่ไม่ใช่ # 1 คำตอบอย่างไร จอนเท่านั้นที่สร้างคอนสตรัคเตอร์ด้วยพารามิเตอร์
แร็พ

1
มีวิธีใดบ้างที่เราจะได้รับตัวอย่างของการสืบทอดโดยใช้กระบวนทัศน์นี้สำหรับผู้สร้าง?
Nathan C. Tresch

1
ตัวอย่าง Constructor ของ @Rap Jon ไม่มีพารามิเตอร์เหมือนกับBox()function :) แต่ตัวอย่างนี้รวมถึงตัวอย่างในคำตอบอื่น ๆ นั้นสามารถขยายได้ง่ายเพื่อยอมรับพารามิเตอร์
Alexander Stepaniuk

2
@AndersonGreen คุณสามารถเพิ่มพารามิเตอร์ลงในกล่องและส่งต่อไปยังตัวสร้างส่วนตัวเป็นพารามิเตอร์ฟังก์ชัน
Gautham C.

1
ไม่จำเป็นต้องมี "ผู้สร้างส่วนตัว" เพียงสร้างสิ่งที่คุณมีในBoxฟังก์ชั่นและคุณก็พร้อมที่จะไป (ก็ยัง "เป็นส่วนตัว") "ส่วนตัว" ใน Javascript หมายถึงสามารถเข้าถึงได้ผ่านขอบเขตศัพท์ ไม่จำเป็นต้องกำหนดให้กับสมาชิก นอกจากนี้: รหัสนี้ผิด มันสร้าง__constructตัวแปรทั่วโลกซึ่งค่อนข้างแย่ varควรจะใช้เพื่อ จำกัด __constructขอบเขตของ
mattbasta

23

ดังนั้นจุดของคุณสมบัติ "คอนสตรัค" คืออะไร? ไม่สามารถคิดได้ว่ามันจะมีประโยชน์มีความคิดอะไรบ้าง?

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

ฉันเขียนบทความที่ค่อนข้างครอบคลุมเกี่ยวกับเรื่องนี้เมื่อไม่กี่ปีที่ผ่านมา: http://joost.zeekat.nl/constructors-considered-mildly-confusing.html


จุดคือการใช้คำหลัก "ใหม่" "d = new Drofto ()" สร้างวัตถุว่างและเรียกใช้ฟังก์ชั่น Drofto ด้วยวัตถุใหม่ที่ถูกล้อมรอบว่า "นี่" ฟังก์ชั่น Drofto มีอิสระที่จะคืนสิ่งใด ๆ แต่เป็นธรรมเนียมในการคืนสิ่งที่ถือว่าเป็นสมาชิกของคลาส Drofto
Juan Lanus

16

ตัวอย่างที่นี่: http://jsfiddle.net/FZ5nC/

ลองเทมเพลตนี้:

<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Name = Name||{};
Name.Space = Name.Space||{};

//============================================================
// Constructor - MUST BE AT TOP OF FILE
//------------------------------------------------------------
Name.Space.ClassName = function Name_Space_ClassName(){}

//============================================================
// Member Functions & Variables
//------------------------------------------------------------
Name.Space.ClassName.prototype = {
  v1: null
 ,v2: null
 ,f1: function Name_Space_ClassName_f1(){}
}

//============================================================
// Static Variables
//------------------------------------------------------------
Name.Space.ClassName.staticVar = 0;

//============================================================
// Static Functions
//------------------------------------------------------------
Name.Space.ClassName.staticFunc = function Name_Space_ClassName_staticFunc(){
}
</script>

คุณต้องปรับเนมสเปซของคุณหากคุณกำหนดคลาสแบบสแตติก:

<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Shape = Shape||{};
Shape.Rectangle = Shape.Rectangle||{};
// In previous example, Rectangle was defined in the constructor.
</script>

ชั้นตัวอย่าง:

<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Shape = Shape||{};

//============================================================
// Constructor - MUST BE AT TOP OF FILE
//------------------------------------------------------------
Shape.Rectangle = function Shape_Rectangle(width, height, color){
    this.Width = width;
    this.Height = height;
    this.Color = color;
}

//============================================================
// Member Functions & Variables
//------------------------------------------------------------
Shape.Rectangle.prototype = {
  Width: null
 ,Height: null
 ,Color: null
 ,Draw: function Shape_Rectangle_Draw(canvasId, x, y){
    var canvas = document.getElementById(canvasId);
    var context = canvas.getContext("2d");
    context.fillStyle = this.Color;
    context.fillRect(x, y, this.Width, this.Height);
 }
}

//============================================================
// Static Variables
//------------------------------------------------------------
Shape.Rectangle.Sides = 4;

//============================================================
// Static Functions
//------------------------------------------------------------
Shape.Rectangle.CreateSmallBlue = function Shape_Rectangle_CreateSmallBlue(){
    return new Shape.Rectangle(5,8,'#0000ff');
}
Shape.Rectangle.CreateBigRed = function Shape_Rectangle_CreateBigRed(){
    return new Shape.Rectangle(50,25,'#ff0000');
}
</script>

ตัวอย่างการสร้างอินสแตนซ์:

<canvas id="painting" width="500" height="500"></canvas>
<script>
alert("A rectangle has "+Shape.Rectangle.Sides+" sides.");

var r1 = new Shape.Rectangle(16, 12, "#aa22cc");
r1.Draw("painting",0, 20);

var r2 = Shape.Rectangle.CreateSmallBlue();
r2.Draw("painting", 0, 0);

Shape.Rectangle.CreateBigRed().Draw("painting", 10, 0);
</script>

ฟังก์ชั่นประกาศกำหนดไว้เป็น AB = function A_B () นี่คือการทำให้สคริปต์ของคุณง่ายต่อการตรวจแก้จุดบกพร่อง เปิดพาเนลองค์ประกอบการตรวจสอบของ Chrome เรียกใช้สคริปต์นี้และขยายการติดตามย้อนกลับที่ดีบั๊ก:

<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Fail = Fail||{};

//============================================================
// Static Functions
//------------------------------------------------------------
Fail.Test = function Fail_Test(){
    A.Func.That.Does.Not.Exist();
}

Fail.Test();
</script>

ตัวอย่างที่เพิ่มเข้ามา เพิ่มข้อมูลเกี่ยวกับการปรับปรุงผลลัพธ์การดีบัก
bitlather

1
อาจเป็นเพราะมันเพิ่มระดับความซับซ้อนที่ไม่จำเป็นให้กับปัญหา เป็นการยากที่จะหาคำตอบในโพสต์ของคุณเนื่องจากการเว้นวรรคชื่ออนาจารและการประกาศคลาสคงที่ อย่าเข้าใจฉันผิดมันเป็นข้อมูลที่ดี แต่ก็มีความสับสนมากกว่าที่จะเป็นประโยชน์หากคุณพยายามทำความเข้าใจ ฉันมีความรู้ความสามารถใน JS และฉันแทบจะไม่เข้าใจว่าคุณกำลังทำอะไรที่นี่หรือทำไมมันถึงเกี่ยวข้องกับ "ฉันจะเป็นผู้สร้างได้อย่างไร"
Bmo

1
ขอบคุณสำหรับความเข้าใจ Bmo มันเป็นการโพสต์ที่ยาวนาน แต่เป็นเพราะฉันไม่เข้าใจการใช้ตัวสร้างถ้ามันไม่ได้ผูกกับวัตถุที่กำหนดไว้อย่างดีและการใช้คลาสแบบคงที่ เมื่อเรียนรู้ C ++ หรือ Java คุณต้องเรียนรู้วิธีการใช้คลาสควบคู่ไปกับวิธีการใช้งานคอนสตรัคเตอร์ นักพัฒนาเว็บได้เพลิดเพลินมากขึ้นนับตั้งแต่ที่ฉันสะดุดกับวิธีการเขียนจาวาสคริปต์นี้และฉันแค่ต้องการแบ่งปัน ฉันขยับซอขึ้นไปด้านบนเพื่อให้หาได้ง่ายขึ้น ฉันหวังว่าจะชี้แจงความสับสนใด ๆ
bitlather

1
@Bmo คุณจริงจังที่สองบรรทัดเกี่ยวกับเนมสเปซทำให้ยากที่จะหาคอนสตรัคเตอร์ด้านล่างโดยเฉพาะอย่างยิ่งได้รับความคิดเห็นคอนสตรัคเตอร์ - จะต้องอยู่ด้านบนของไฟล์? ยินดีต้อนรับอย่างมากชุมชน javascript dev ให้ตัวอย่างกับเนมสเปซอย่างไม่เจาะจงละเว้นเนมสเปซทำให้เกิดข้อผิดพลาดในการค้นหาข้อผิดพลาดเมื่อชื่อแคลช เป็นเรื่องน่าเศร้าที่เห็นว่า js devs คิดว่าพวกเขาคัดลอกข้อความจากโพสต์บนอินเทอร์เน็ตและทำสิ่งที่คล้ายกับสิ่งที่พวกเขาต้องการทำงานให้เสร็จสมบูรณ์
user3285954

1
ปัญหาหลักของ js และการพัฒนาเว็บโดยทั่วไปคือ devs ส่วนใหญ่เพิกเฉยต่อสิ่งที่อุตสาหกรรมสร้างขึ้นใน 50 ปีที่ผ่านมาและคิดว่าพวกเขาสามารถเรียกอาแจ็กซ์ได้ว่าพวกเขาเป็นราชา เศร้ามากที่เห็นว่าใช้เวลาหลายปีกว่าจะเริ่มใช้รูปแบบและวิธีปฏิบัติที่รู้จักกันดีในจาวาสคริปต์
user3285954

10

นี่คือตัวสร้าง:

function MyClass() {}

เมื่อคุณทำ

var myObj = new MyClass();

MyClass ถูกดำเนินการและวัตถุใหม่ถูกส่งคืนของคลาสนั้น


1
เพื่อให้ชัดเจนว่าสิ่งนี้หมายความว่าอะไรอยู่ด้านบนสุดของชั้นเรียนของคุณคุณสามารถพูดได้alert(valuePassedInAsArgument);และสิ่งนี้จะทำงานหนึ่งครั้งสำหรับแต่ละอินสแตนซ์ดังนั้นทั้งชั้นจึงเป็นตัวสร้าง
Martin Lyne

new object is returned of that class- มันไม่เหมือนกับวัตถุใหม่ที่ส่งคืนของฟังก์ชันนั้นหรือไม่
Don Cheadle

ในฟังก์ชั่นจาวาสคริปต์คือวัตถุ
Leo

8

ฉันพบว่าบทช่วยสอนนี้มีประโยชน์มาก วิธีการนี้ใช้โดยปลั๊กอิน jQuery ส่วนใหญ่

http://www.htmlgoodies.com/html5/tutorials/create-an-object-oriented-javascript-class-constructor.html#fbid=OVYAQL_TDpK

var Class = function(methods) {   
    var klass = function() {    
        this.initialize.apply(this, arguments);          
    };  

    for (var property in methods) { 
       klass.prototype[property] = methods[property];
    }

    if (!klass.prototype.initialize) klass.prototype.initialize = function(){};      

    return klass;    
};

ตอนนี้

var Person = Class({ 
    initialize: function(name, age) {
        this.name = name;
        this.age  = age;
    },
    toString: function() {
        return "My name is "+this.name+" and I am "+this.age+" years old.";
    }
}); 

var alice = new Person('Alice', 26);
alert(alice.name); //displays "Alice"
alert(alice.age); //displays "26"
alert(alice.toString()); //displays "My name is Alice and I am 26 years old" in most browsers.
//IE 8 and below display the Object's toString() instead! "[Object object]"

10
ฉันประจบประแจงเมื่อใดก็ตามที่ฉันเห็นคนใช้klass
Madbreaks

8

รูปแบบนี้ให้บริการฉันดี ด้วยรูปแบบนี้คุณสามารถสร้างคลาสในไฟล์แยกกันโหลดลงในแอพโดยรวมของคุณ "ตามต้องการ"

// Namespace
// (Creating new if not instantiated yet, otherwise, use existing and just add to it)
var myApp = myApp || {};

// "Package" 
// Similar to how you would establish a package in other languages
(function() {

// "Class"
var MyClass = function(params) {
    this.initialize(params);
}

    // "Private Static" vars 
    //    - Only accessible to functions in this class.
    //    - Doesn't get wiped out when we create a new instance.
    var countInstances = 0;
    var allInstances = [];

    // "Private Static" functions 
    //    - Same as above, but it's a function accessible 
    //      only to other functions in this class.
    function doSomething(){
    }

    // "Public Static" vars
    //    - Everyone has access.
    //    - Doesn't get wiped out when we create a new instance.
    MyClass.counter = 0;

    // "Public Static" functions
    //    - Same as above, but anyone can call this "static method".
    //    - Kinda like a singleton class situation.
    MyClass.foobar = function(){
    }

    // Public properties and methods are built into the "prototype"
    //    - This is how each instance can become unique unto itself.
    //    - Establishing "p" as "local" (Static Private) variable 
    //      simply so we don't have to keep typing "MyClass.prototype" 
    //      for each property and function.
var p = MyClass.prototype;

    // "Public" vars
    p.id = null;
    p.firstname = null;
    p.lastname = null;

    // "Private" vars
    //    - Only used by "this" instance.
    //    - There isn't "true" privacy for each 
    //      instance so we have to fake it. 
    //    - By tradition, we indicate "privacy"  
    //      by prefixing it with an underscore. 
    //    - So technically, anyone can access, but we simply 
    //      don't tell anyone about it (e.g. in your API)
    //      so no one knows about it :)
    p._foo = null;

    p.initialize = function(params){
        this.id = MyClass.counter++;
        this.firstname = params.firstname;
        this.lastname = params.lastname;
        MyClass.counter++;
        countInstances++;
        allInstances.push(this);
    }

    p.doAlert = function(theMessage){
        alert(this.firstname + " " + this.lastname + " said: " + theMessage + ". My id:" + this.id + ".  Total People:" + countInstances + ". First Person:" + allInstances[0].firstname + " " + allInstances[0].lastname);
    }


// Assign class to app
myApp.MyClass = MyClass;

// Close the "Package"
}());

// Usage example:
var bob = new myApp.MyClass({   firstname   :   "bob",
                                lastname    :   "er"
                            });

bob.doAlert("hello there");

นั่นคือตัวแปรอินสแตนซ์ แต่มีการเข้าถึง "สาธารณะ" ไม่ใช่ "ส่วนตัว" ใน C ++ หรือ Java
Potatoswatter

คุณจะสร้างตัวแปรส่วนตัว (ในความหมายดั้งเดิม) ที่เกี่ยวข้องกับอินสแตนซ์อย่างไร แต่ไม่พบได้ทั่วไปในทุกอินสแตนซ์
บ๊อบ

ดูเว็บไซต์ของDouglas Crockfordเขาเป็นหนึ่งในนักออกแบบภาษาและเป็นผู้มีอำนาจสูงสุด ฉันไม่ได้ทำตามรูปแบบของเขาเสมอไป แต่โดยทั่วไปแล้วตัวแปรส่วนตัวคือท้องถิ่นvarในตัวสร้าง (หรืออาร์กิวเมนต์ของฟังก์ชันหรือในฟังก์ชันที่เหมือนกับตัวสร้าง)
Potatoswatter

ขอบคุณสำหรับเคล็ดลับ ... หน้าต่อไปนี้อธิบายสิ่งที่ฉันกำลังมองหา: javascript.crockford.com/private.html
bob

โอ้ขอโทษที่ไม่ได้ทดสอบลิงก์: P
Potatoswatter

8

ใช่คุณสามารถกำหนดนวกรรมิกภายในการประกาศคลาสเช่นนี้:

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

สำหรับ vaersion IE> 12
zloctb


1
นี่เป็นคำตอบสำหรับคำถามเท่านั้น : /
MarcD

6

ฉันเดาว่าฉันจะโพสต์สิ่งที่ฉันทำกับการปิด javascript เนื่องจากยังไม่มีใครใช้การปิด

var user = function(id) {
  // private properties & methods goes here.
  var someValue;
  function doSomething(data) {
    someValue = data;
  };

  // constructor goes here.
  if (!id) return null;

  // public properties & methods goes here.
  return {
    id: id,
    method: function(params) {
      doSomething(params);
    }
  };
};

ความคิดเห็นและข้อเสนอแนะเกี่ยวกับการแก้ปัญหานี้ยินดีต้อนรับ :)


1
ความเห็นสองสามข้อ: 1) คำสั่งถ้า (! id) ไม่ปลอดภัยค่าเช่น 0 หรือเท็จจะทำให้ประเมินค่าจริงและส่งคืนค่าว่าง ฉันเดาว่าคุณต้องการตรวจสอบ undefined หรือ null ซึ่งในกรณีนี้ === null และ === undefined จะดีกว่า 2) สิ่งนี้คล้ายกับรูปแบบของโมดูลมากขึ้น ( อย่างพอเพียง good.com/2010/3/JavaScript-Module-Pattern-In-Depth ) เทียบกับตัวสร้างความแตกต่างของโมดูลจะส่งคืนวัตถุจากฟังก์ชันในขณะที่ตัวสร้างสร้างวัตถุเมื่อ จับคู่กับคำหลักใหม่และในกรณีนั้นคุณจะต้องตั้งค่าเป็น 'นี้' แทนวัตถุ
รวย

4

การใช้ตัวอย่างของ Nick ด้านบนคุณสามารถสร้างนวกรรมิกสำหรับวัตถุที่ไม่มีพารามิเตอร์โดยใช้คำสั่ง return เป็นคำสั่งสุดท้ายในการกำหนดวัตถุของคุณ คืนค่าฟังก์ชั่น Constructor ของคุณตามด้านล่างและมันจะรันโค้ดใน __ สร้างทุกครั้งที่คุณสร้างวัตถุ:

function Box()
{
   var __construct = function() {
       alert("Object Created.");
       this.color = 'green';
   }

  this.color = '';

   this.getColor = function() {
       return this.color;
   }

   __construct();
}

var b = new Box();

1
คุณไม่ได้ส่งคืนฟังก์ชันคอนสตรัคเตอร์คุณแค่เรียกมัน
David Conrad

หากคุณพยายามที่จะใช้this.getColor();ในบรรทัดข้างต้นalert("Object Created.");ไม่มีอะไรจะแจ้งเตือน จะมีข้อผิดพลาดเช่น "ไม่ได้กำหนด getColor" หากคุณต้องการสร้างโครงสร้างเพื่อให้สามารถเรียกใช้เมธอดอื่นในวัตถุนั้นจะต้องมีการกำหนดหลังจากวิธีอื่นทั้งหมด ดังนั้นแทนที่จะโทร__construct();ไปที่บรรทัดสุดท้ายให้กำหนดโครงสร้างที่นั่นและวางไว้()หลังจากนั้นเพื่อบังคับให้ดำเนินการอัตโนมัติ
thinsoldier

การแก้ไข การเพิ่ม()ที่ส่วนท้ายของนิยาม __ โครงสร้างยังคงทำให้เกิดข้อผิดพลาด ฉันต้องโทรหาสาย__construct();ของตัวเองเหมือนในรหัสดั้งเดิมเพื่อหลีกเลี่ยงข้อผิดพลาด
thinsoldier

4

อาจจะเป็นเรื่องง่ายขึ้นเล็กน้อย แต่ข้างล่างนี้คือสิ่งที่ฉันคิดไว้ตอนนี้ในปี 2560:

class obj {
  constructor(in_shape, in_color){
    this.shape = in_shape;
    this.color = in_color;
  }

  getInfo(){
    return this.shape + ' and ' + this.color;
  }
  setShape(in_shape){
    this.shape = in_shape;
  }
  setColor(in_color){
    this.color = in_color;
  }
}

ในการใช้คลาสข้างต้นฉันมีดังต่อไปนี้:

var newobj = new obj('square', 'blue');

//Here, we expect to see 'square and blue'
console.log(newobj.getInfo()); 

newobj.setColor('white');
newobj.setShape('sphere');

//Since we've set new color and shape, we expect the following: 'sphere and white'
console.log(newobj.getInfo());

อย่างที่คุณเห็นคอนสตรัคเตอร์ใช้สองพารามิเตอร์และเราตั้งค่าคุณสมบัติของวัตถุ นอกจากนี้เรายังเปลี่ยนสีและรูปร่างของวัตถุโดยใช้setterฟังก์ชั่นและพิสูจน์ว่าการเปลี่ยนแปลงยังคงอยู่เมื่อมีการเรียกgetInfo()หลังจากการเปลี่ยนแปลงเหล่านี้

สายไปหน่อย แต่ฉันหวังว่านี่จะช่วยได้ ฉันทำการทดสอบด้วยการmochaทดสอบหน่วยและมันใช้งานได้ดี


3

พวกเขาทำถ้าคุณใช้Typescript - โอเพ่นซอร์สจาก MicroSoft :-)

class BankAccount {
 balance: number;
 constructor(initially: number) {
 this.balance = initially;
 }
 deposit(credit: number) {
 this.balance += credit;
 return this.balance;
 }
}

typescript ช่วยให้คุณสร้าง OO 'ปลอม' ที่รวบรวมไว้ในโครงสร้าง javascript หากคุณกำลังเริ่มต้นโครงการขนาดใหญ่อาจช่วยให้คุณประหยัดเวลาได้มาก

http://www.typescriptlang.org/Content/TypeScript%20Language%20Specification.pdf

โค้ดด้านบนได้รับ 'รวบรวม' เป็น:

var BankAccount = (function () {
    function BankAccount(initially) {
        this.balance = initially;
    }
    BankAccount.prototype.deposit = function (credit) {
        this.balance += credit;
        return this.balance;
    };
    return BankAccount;
})();

ฉันกำลังทำงานในโครงการขนาดใหญ่และฉันพยายามโน้มน้าวให้คนอื่นรู้ว่า TypeScript จะทำให้เราทำงานได้เร็วขึ้น เราจะดูว่ามันเป็นอย่างไร
wootscootinboogie

@wootscootinboogie ในหนึ่งวัน (สิ้นสุดตอน 5.30 น. ตอนนี้) ฉันค่อนข้างไกลและค่อนข้างสบายใจกับมัน ฉันขอแนะนำให้อ่านสเป็คผ่านและในขณะที่คุณสามารถข้ามครึ่งของสิ่งที่เป็นจริงที่คุณกำลังทำเองชอบอ่านอย่างน้อยหนึ่งครั้ง วิดีโอของผู้ชายคนนี้เป็นอย่างดีyoutube.com/user/basaratali/videos ขอให้โชคดี)
Simon_Weaver

1

ใน JavaScript ประเภทการร้องขอจะกำหนดพฤติกรรมของฟังก์ชัน:

  • การร้องขอโดยตรง func()
  • วิธีการภาวนาบนวัตถุ obj.func()
  • การเรียกใช้Constructornew func()
  • การร้องขอทางอ้อมfunc.call()หรือfunc.apply()

ฟังก์ชั่นถูกเรียกใช้เป็นตัวสร้างเมื่อเรียกใช้newโอเปอเรเตอร์:

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

var myCat = new Cat('Sweet'); // Cat function invoked as a constructor

ตัวอย่างหรือวัตถุต้นแบบใน JavaScript มีคุณสมบัติconstructorซึ่งหมายถึงฟังก์ชั่นการสร้าง

Cat.prototype.constructor === Cat // => true
myCat.constructor         === Cat // => true

ตรวจสอบโพสต์นี้เกี่ยวกับคุณสมบัติคอนสตรัค


0

ในขณะที่ใช้เทมเพลตที่ยอดเยี่ยมของ Blixt จากด้านบนฉันพบว่ามันไม่สามารถทำงานได้ดีกับการสืบทอดหลายระดับ ดังนั้นนี่คือวิธีแก้ไขง่ายๆ - หากคุณต้องการรับมรดกหลายระดับแทนที่จะthis.constructor.super.call(this, surName);ใช้chainSuper(this).call(this, surName);กับฟังก์ชั่นลูกโซ่ที่กำหนดไว้ดังนี้:

function chainSuper(cls) {
  if (cls.__depth == undefined) cls.__depth = 1; else cls.__depth++;
  var depth = cls.__depth;
  var sup = cls.constructor.super;
  while (depth > 1) {
    if (sup.super != undefined) sup = sup.super;
    depth--;
  }
  return sup;
}

0

http://www.jsoops.net/ค่อนข้างดีสำหรับ oop ใน Js หากจัดเตรียมตัวแปรและฟังก์ชั่นส่วนตัว, การป้องกัน, สาธารณะและคุณสมบัติการสืบทอด รหัสตัวอย่าง:

var ClassA = JsOops(function (pri, pro, pub)
{// pri = private, pro = protected, pub = public

    pri.className = "I am A ";

    this.init = function (var1)// constructor
    {
        pri.className += var1;
    }

    pub.getData = function ()
    {
        return "ClassA(Top=" + pro.getClassName() + ", This=" + pri.getClassName()
        + ", ID=" + pro.getClassId() + ")";
    }

    pri.getClassName = function () { return pri.className; }
    pro.getClassName = function () { return pri.className; }
    pro.getClassId = function () { return 1; }
});

var newA = new ClassA("Class");

//***Access public function
console.log(typeof (newA.getData));
// function
console.log(newA.getData());
// ClassA(Top=I am A Class, This=I am A Class, ID=1)

//***You can not access constructor, private and protected function
console.log(typeof (newA.init));            // undefined
console.log(typeof (newA.className));       // undefined
console.log(typeof (newA.pro));             // undefined
console.log(typeof (newA.getClassName));    // undefined

0

เพียงเพื่อเสนอความหลากหลาย ds.oopเป็นวิธีที่ดีในการประกาศคลาสด้วย constructors ใน javascript รองรับการสืบทอดได้ทุกประเภท (รวมถึง 1 ประเภทที่แม้แต่ c # ไม่รองรับ) รวมถึงอินเตอร์เฟสที่ดี

var Color = ds.make.class({
    type: 'Color',
    constructor: function (r,g,b) { 
        this.r = r;                     /* now r,g, and b are available to   */
        this.g = g;                     /* other methods in the Color class  */
        this.b = b;                     
    }
});
var red = new Color(255,0,0);   // using the new keyword to instantiate the class

0

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

// Function constructor

   var calculator=function(num1 ,num2){
   this.name="This is function constructor";
   this.mulFunc=function(){
      return num1*num2
   };

};

var objCal=new calculator(10,10);// This is a constructor in java script
alert(objCal.mulFunc());// method call
alert(objCal.name);// property call

//Constructors With Prototypes

var calculator=function(){
   this.name="Constructors With Prototypes";
};

calculator.prototype.mulFunc=function(num1 ,num2){
 return num1*num2;
};
var objCal=new calculator();// This is a constructor in java script
alert(objCal.mulFunc(10,10));// method call
alert(objCal.name); // property call

-2

ในกรณีส่วนใหญ่คุณต้องประกาศคุณสมบัติที่คุณต้องการก่อนจึงจะสามารถเรียกวิธีการที่ส่งผ่านข้อมูลนี้ได้ หากคุณไม่จำเป็นต้องตั้งค่าคุณสมบัติเริ่มต้นคุณสามารถเรียกวิธีการภายในวัตถุเช่นนั้นได้ อาจไม่ใช่วิธีที่สวยที่สุดในการทำเช่นนี้ แต่ก็ยังใช้งานได้

var objectA = {
    color: ''; 
    callColor : function(){
        console.log(this.color);
    }
    this.callColor(); 
}
var newObject = new objectA(); 
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.