2013-04-19 29 views
22

Tôi đã thấy một vài cách khác nhau để khởi tạo các đối tượng trong javascript, muốn biết các lợi ích/nhược điểm của các cách tiếp cận khác nhau và tại sao bạn sẽ sử dụng một đối tượng khác.Các đối tượng tạo Javascript - nhiều cách tiếp cận, bất kỳ sự khác biệt nào?

Cách tiếp cận 1

var obj = { 
    prop: value, 
    . 
    . 
    . 
} 

Tiếp cận một là cách tiếp cận tiêu chuẩn, không có gì mới :)

Cách tiếp cận 2

var obj = new function() { 
    var prop1 = value1; 
    var fn1 = function() { 
    }; 
    . 
    . 
    . 

    this.prop2 = value2; 
    . 
    . 
    . 
}(); 

Cách tiếp cận chức năng, tôi muốn so sánh phương pháp này với phương pháp tiếp cận 3. Cách tiếp cận chức năng chủ yếu được sử dụng để đóng gói (sửa?)

Cách tiếp cận 3

var obj = (function() { 
    var prop1 = value1; 
    var fn1 = function() { 
    }; 
    . 
    . 
    . 

    return { 
     prop2: value2, 
     . 
     . 
     . 
    } 
})(); 

Với phương pháp này, tôi hoàn toàn không thấy lý do đằng sau việc sử dụng của nó. Nó khác với cách tiếp cận 2 như thế nào? Cả hai có thể được sử dụng để đóng gói logic.

Có phải để chúng tôi có thể chuyển các tham số, vì vậy chúng tôi có thể giải quyết mọi xung đột tiềm năng không? Ví dụ: cú pháp $ của jquery - nhưng bạn cũng có thể làm điều này với cách tiếp cận 2 ...

Cảm ơn.


Edit:


Tôi biết phương pháp này 1 và 3 là tương tự (ở chỗ chúng cả hai đối tượng cửa sổ mới) tuy nhiên tiếp cận 3 cũng tạo ra một đóng cửa. Cách tiếp cận 2 cũng có.

Đó là cơ sở cho câu hỏi của tôi thực sự, cả 2 và 3 đều tạo ra những đóng cửa, nhưng sự khác biệt giữa chúng là gì.

+0

Trong phương pháp tiếp cận 2 từ khóa 'mới' không nên ở đó. – Halcyon

+2

@FritsvanCampen - Có. Điều này tạo ra một đối tượng mới từ hàm khởi tạo (ẩn danh). –

+1

nếu từ khóa 'mới' không có, nó sẽ là một lớp. – macool

Trả lời

10

Trong phương pháp # 2 và # 3, constructor thuộc tính của đối tượng kết quả sẽ khác nhau.

Trên thực tế nó có nghĩa là phương pháp thứ hai cho phép bạn nhanh chóng hơn một đối tượng bằng cách sử dụng chức năng constructor nặc danh:

x = new function() { alert(1) }; 
y = new x.constructor; // shows the message too 

Câu trả lời trên xuống Module pattern vs. instance of an anonymous constructor bao gồm một trích dẫn từ Douglas Crockford, trong đó ông giải thích tại sao ông cho rằng cách tiếp cận # 3 tốt hơn # 2.

+0

Rất đẹp. Tôi đã không nghĩ về tài sản 'constructor'. –

0

Không có nhiều sự khác biệt giữa phương pháp 2 và 3 đối với các đối tượng một lần. (Nếu bạn đặt tên hàm được sử dụng trong phương pháp 2, bạn đã định nghĩa một hàm tạo có thể sử dụng lại được.) Ấn tượng của tôi là cách tiếp cận 3 thường được sử dụng cho các tình huống này, nhưng tôi không thấy nhiều sự khác biệt giữa chúng.

Cần lưu ý rằng cả hai phương pháp tiếp cận 2 và 3 có thể lấy đối số:

var approach2Obj = new function(formalArg) { 
    var privateProp = ...; 
    this.publicProp = ...; 
    // more constructor logic 
)(actualArg); 

var approach3Obj = (function(formalArg) { 
    var privateProp = ...; 
    // more creation logic 
    return { 
     publicProp : ...; 
    }; 
}(actualArg)); 

T.B. Như @Alexey Lebedev points out in his answer, một sự khác biệt giữa hai (có lẽ là duy nhất) là approach2Obj.constructorapproach3Obj.constructor sẽ khác nhau. approach3Obj.constructor sẽ giống hệt Object, trong khi approach2Obj.constructor sẽ là hàm ẩn danh.

+0

Xin lỗi về cơ bản prop1 là để chỉ các biến riêng. Logic của hàm có thể tiếp tục và sử dụng các biến này ... Tôi sẽ cập nhật để phản ánh điều này – Umair

+0

@Umair - Tôi không nghĩ rằng câu trả lời của tôi thay đổi. Phương pháp tiếp cận 2 và 3 về cơ bản là tương đương. –

4

Cách tiếp cận thứ nhất và thứ ba gần như giống nhau, theo cách mà cả hai tạo ra một đối tượng theo nghĩa đen, là con trực tiếp của lớp Object.Sự khác biệt giữa chúng là trong cách tiếp cận thứ ba bạn có thể có một số loại đóng gói tài sản:

var obj = (function() { 
    var prop = {}; 

    return { 
     prop2: function(){ return prop }; 
    } 
})(); 

Performance-khôn ngoan bạn có thể xem xét rằng cách tiếp cận thứ ba tạo ra đóng cửa, trong khi người đầu tiên không!

Tuy nhiên, trong phương pháp thứ hai, bạn chỉ đang tạo đối tượng mới từ một lớp ẩn danh không phải là con trực tiếp của lớp Object.

Hình thức đúng đắn về cách tiếp cận thứ hai là này (ít nhất đó là tiêu chuẩn ECMA):

var obj = new function() { 
    var prop1 = value1; 

    this.prop2 = value2; 
}(); 

Sự khác biệt giữa phương pháp 2 và 3 chỉ là chuỗi thừa kế của họ: (giả sử obj2 được từ cách tiếp cận thứ 2 và obj3 là từ cách tiếp cận thứ 3)

obj2.__proto__ == Object.prototype; // false 
obj3.__proto__ == Object.prototype; // true 

obj2 được tạo ra từ một lớp vô danh bản thân:

obj2.__proto__.__proto__ == Object.prototype; // true (there's 2 level of inheritance here) 
+0

Ý bạn là gì bởi "con trực tiếp"? –

+1

bất kỳ đối tượng theo nghĩa đen nào được thừa hưởng trực tiếp từ 'Object.prototype' làm cho nó trực tiếp con của lớp' Object': 'obj .__ proto__ == Object.prototype' –

0

Câu hỏi của bạn phải là 2 Phương pháp tiếp cận vì Cách tiếp cận 3 giống hệt như Cách tiếp cận 1 chỉ cách để tạo điều đó bằng chức năng tự thực thi.

Về sự khác biệt khi bạn tạo một đối tượng như Phương pháp tiếp cận 1 bạn có thể nghĩ về nó như một đối tượng chỉ có chức năng tĩnh như trong java. do đó, nó luôn sống và bạn không thực hiện dụ ra khỏi nó (tương tự như Singleton) - vì vậy khi bạn thực hiện đối tượng này:

var obj = { 
    prop: value, 
    func: function(){ 
    alert(this.prop); 
    } 
}; 

Bạn có thể gọi nó là ngay lập tức:

obj.prop = 'something else'; 
obj.func(); 

Cách tiếp cận 2 (không có mới như những nhận xét bạn có được) là một đối tượng cổ điển mà bạn có thể tạo ra các trường hợp - làm kế thừa (với "thủ thuật" js) và vân vân:

function Person(firstName,lastName){ // or var Person = function(... 
    this.firstName = firstName; 
    this.lastName= lastName; 

    this.getFullName = function(){ 
     return this.firstName + ' ' + this.lastName; 
    } 
} 

//use 
var person1 = new Person('yair','lapid'); 
var person2 = new Person('Naftali','Bennet'); 

you can put it in an array etc... 
var arr = [person1,person2, new Person('shelly','yekimovits')]; 
+0

Phương pháp tiếp cận 3 tạo ra một đóng; cách tiếp cận 1 không. Điều đó làm cho chúng khá khác nhau. –

+0

Nhưng đó không phải là câu hỏi - bạn có thể gọi cũng là một hàm bình thường trả về một đối tượng hoặc một máy bay trả về một đối tượng - anh ta hỏi về sự khác biệt của việc tạo các đối tượng - và đây không phải là định nghĩa đúng của btw ... – Adidi

2

Cách tiếp cận 1
Đây là một đối tượng duy nhất, không có lớp và bạn không thể xác định dễ dàng hơn nếu nó phức tạp

var obj = { 
    prop: value 
} 

Cách tiếp cận 2
Một chức năng không nặc danh.Nó sẽ tạo ra một đối tượng ra khỏi một 'lớp', normalle hàm được lưu lại dưới dạng một tên lớp và có thể tạo ra nhiều đối tượng cùng loại một cách dễ dàng như dưới đây:

var Bycicle= function() { 
    var prop1 = value1; 

    this.prop2 = value2; 
} 
var obj1 = new Bycicle(), 
    obj2 = new Bycicle(); 

Cách tiếp cận 3
Một chức năng ẩn danh , các biến từ bên ngoài chức năng không thể can thiệp với các biến bên trong hàm:

var a = 10; 
var obj = (function() { 
    alert(a); // Alerts undefined 
    var prop1 = value1; 
    alert(prop1); // alerts the value of value1 
    return { 
     prop2: value2; 
    } 
})(); // Within the() you can pass arguments to the anonymous function. 

Thông tin thêm về chức năng ẩn danh: http://helephant.com/2008/08/23/javascript-anonymous-functions/

cách tiếp cận khác
Ngoài ra còn có một Object.create()new Object() để tạo ra các đối tượng mới, mà cả hai đều giống nhau như tiếp cận 1.

Kết luận
Cuối cùng, đối tượng sẽ luôn luôn là như nhau ngoại trừ cho cái thứ 3, bởi vì nó ẩn danh.

0

Để hiểu cách tiếp cận 2, người đọc cần biết một số điều khá kỹ thuật về cách hoạt động của từ khóa mới. Cụ thể là nó sẽ thực sự gọi hàm ẩn danh là một hàm tạo, thay vì khởi tạo một đối tượng hàm mới và đổ nó vào biến obj.

Để hiểu cách tiếp cận 3, người đọc chỉ cần hiểu mẫu IIFE. Mô hình đó đã trở nên rất phổ biến trong mã javascript trong hai năm qua và đó có thể là lý do tại sao phiên bản đó thường được sử dụng hơn.

Cả hai phiên bản được sử dụng để sản xuất đóng gói và cả hai phiên bản đều yêu cầu hiểu biết về tính năng ngôn ngữ phức tạp để hiểu. Tuy nhiên, tính năng ngôn ngữ cần thiết trong phương pháp tiếp cận ba thường được biết đến nhiều hơn so với tính năng ngôn ngữ cần thiết để hiểu cách tiếp cận hai. Đó là lý do tại sao cách tiếp cận ba thường được sử dụng trong tự nhiên.

+0

Một đồng nghiệp một khi loại bỏ từ khóa 'mới' từ một nhà xây dựng ẩn danh vì anh ta nghĩ đó là một lỗi đánh máy. –

2

Ngoài ra còn có:

var obj = Object.create({prop: ...}); 

này hoạt động bằng cách thiết lập một nguyên mẫu. Sử dụng nguyên mẫu hiệu quả hơn nhiều nếu bạn định có nhiều đối tượng chia sẻ các thuộc tính hoặc phương thức.

var proto = {foo: function() {}}, 
    obj1 = Object.create(proto), 
    obj2 = Object.create(proto), 
    obj3 = {foo: function() {}}, 
    obj4 = {foo: function() {}}; 

Trong ví dụ này, hàm obj1 và obj2 dùng hàm "foo", được xác định trong "proto". Trong khi đó, obj3 và obj4 đều có "foo" của riêng mình. Nếu bạn đang tạo nhiều đối tượng với nhiều thuộc tính, điều này có thể tạo ra sự khác biệt lớn về mức tiêu thụ bộ nhớ và thậm chí hiệu suất.

Lợi ích này được chia sẻ bằng cách sử dụng từ khóa "mới" nếu bạn sử dụng hàm được đặt tên và gán thuộc tính cho nguyên mẫu của hàm (ví dụ: f.prototype.prop) trước khi sử dụng mới.

16

7 cách để tạo các đối tượng trong JavaScript:

1. Object constructor

Cách đơn giản nhất để tạo ra một đối tượng là sử dụng các nhà xây dựng Object: view plainprint?

var person = new Object(); 
person.name = "Diego"; 
person.getName = function(){ 
    return this.name; 
}; 

2. Literal ký hiệu

view plainprint?

var person = { 
    person.name : "Diego", 
    person.getName : function(){ 
     return this.name; 
    } 
} 

3. chức năng Factory

Chức năng Factory cho phép để đóng gói và tái sử dụng logic để tạo các đối tượng tương tự. Nó thúc đẩy bất kỳ cấu trúc nào trước đây cho điều này. Hoặc: xem dấu vân tay?

var newPerson=function(name){ 
    var result = new Object(); 
    result.name = name; 
    result.getName = function(){ 
     return this.name; 
    }; 
    return result; 
}; 
var personOne = newPerson("Diego"); 
var personTwo = newPerson("Gangelo"); 
console.log(personOne.getName()); // prints Diego 
console.log(personTwo.getName()); // prints Gangelo 

Hoặc:

view plainprint? 
var newPerson=function(name){ 
    return { 
     person.name : name, 
     person.getName : function(){ 
      return this.name; 
     }; 
}; 
var personOne = newPerson("Diego"); 
var personTwo = newPerson("Gangelo"); 
console.log(personOne.getName()); // prints Diego 
console.log(personTwo.getName()); // prints Gangelo 

4. Chức năng Constructor

Trong Javascript có thể gọi bất kỳ chức năng với các nhà điều hành mới ở phía trước của nó. Cho hàm F, cho F mới(): một đối tượng trống X mới được tạo. X được đặt làm ngữ cảnh cho ý nghĩa F trong suốt F, điểm này thành X. X được trả lại là kết quả của F xem dấu vân tay?

function Person(name){ 
     this.name = name; 
     this.getName = function(){ 
      return this.name; 
     }; 
}; 
var personOne = new Person("Diego"); 
console.log(personOne.getName()); // prints Diego 
console.log(personOne instanceOf Person); // prints true 
console.log(personOne.constructor === Person); // prints true 
console.log(personOne instanceOf Object); // prints true 

5. Nguyên mẫu

Chức năng rất đặc biệt trong Javascript. Chúng là các đối tượng, chúng có thể tạo ra các đối tượng khác và chúng tự động nhận được một trường được gọi là prototype. Một nguyên mẫu là một đối tượng đơn giản với một trường duy nhất, được gọi là hàm tạo, trỏ đến chính hàm đó. Điều gì làm cho nó đặc biệt là mọi đối tượng được tạo ra thông qua một hàm kế thừa nguyên mẫu của hàm. xem dấu vân tay?

function Person(){}; 
Person.prototype.name = "Diego"; 
var personOne = new Person(); 
var personTwo = new Person(); 
console.log(personOne.constructor == Person); // prints true 
console.log(personOne.name); // prints Diego 
console.log(personTwo.constructor == Person); // prints true 
console.log(personTwo.name); // prints Diego 

6. Chức năng/Prototype kết hợp

Chức năng/mẫu kết hợp, bạn sẽ tưởng tượng, lợi dụng cả hai phương pháp tiếp cận :) view plainprint?

function Person(name){ 
     this.name = name; 
}; 
Person.prototype.getName = function(){ 
      return this.name; 
     }; 
var personOne = new Person("Diego"); 
var personTwo = new Person("Filippo"); 
console.log(personOne.getName()); // prints Diego 
console.log(personTwo.getName()); // prints Filippo 
console.log(personOne.getName === personTwo.getName) //prints true 

7. Singleton

Đôi khi, bạn có thể muốn chắc chắn rằng chỉ có một trường hợp duy nhất của một lớp nào đó tồn tại. Để có được Singleton trong Javascript cũng đơn giản như xác định và gọi hàm tạo cùng một lúc: xem dấu vân tay?

var singleton = new function(){ 
    this.name = "ApplicationName"; 
}; 
+0

"Xem dấu vân tay" là gì? thậm chí có nghĩa là gì? – Taurus

Các vấn đề liên quan