52

thời gian gần đây tôi đã cố gắng để tạo ra một đối tượng như thế này:Thuộc tính đối tượng JavaScript có thể tham chiếu đến thuộc tính khác của cùng một đối tượng không?

var carousel = { 
     $slider: $('#carousel1 .slider'), 
     panes: carousel.$slider.children().length 
    }; 

ý định của tôi là để cải thiện hiệu suất selector của jQuery bởi bộ nhớ đệm kết quả $('#carousel1 .slider') trong một tài sản đối tượng, và để giữ mã ngắn gọn và tương đối khô.

Tuy nhiên, điều này không hiệu quả. Khi mã được thực hiện, nó đã ném một ngoại lệ khi cố gắng phân tích giá trị của panes, phàn nàn rằng carousel không được xác định.

Điều này có ý nghĩa, vì tôi giả định rằng carousel không được khai báo đầy đủ cho đến khi câu lệnh gán được thực thi đầy đủ. Tuy nhiên, tôi muốn tránh phải dùng đến này:

var carousel = {}; 
carousel.$slider = $('#carousel1 .slider'); 
carousel.panes = carousel.$slider.children().length; 

Đó không phải là quá tồi tệ hơn nhiều, nhưng đối tượng carousel sẽ có nhiều hơn các thuộc tính dựa trên các giá trị của các tài sản khác, vì vậy mà có thể nhanh chóng trở thành verbose.

Tôi đã thử sử dụng this, nhưng không có kết quả. Tôi cũng có thể không được sử dụng nó một cách chính xác, hoặc đó có thể không phải là một cách tiếp cận hợp lệ anyway.

Có cách nào để các thuộc tính của đối tượng tham chiếu đến các thuộc tính khác của cùng một đối tượng hay không, trong khi đối tượng đó vẫn đang được khai báo? (! Thanks, guys)


Dựa trên Matthew Flaschen và câu trả lời casablanca, tôi nghĩ rằng đây là những phiên bản của mã thực tế của tôi mà tôi muốn kết thúc với, dựa trên mỗi phương pháp:

// Matthew Flaschen 

var carousel = new (function() { 
    this.$carousel = $('.carousel'); 
    this.$carousel_window = this.$carousel.find('.window'); 
    this.$carousel_slider = this.$carousel.find('.slider'); 
    this.$first_pane = this.$carousel.find('.slider').children(':first-child'); 
    this.panes = this.$carousel_slider.children().length; 
    this.pane_gap = this.$first_pane.css('margin-right'); 
})(); 

// casablanca 

var $carousel = $('.carousel'), 
    $carousel_slider = $carousel.find('.slider'), 
    $first_pane: $carousel.find('.slider').children(':first-child'); 

var properties = { 
    $carousel_window: $carousel.find('.window'), 
    panes: $carousel_slider.children().length, 
    pane_gap: $first_pane.css('margin-right') 
}; 

properties.$carousel = $carousel; 
properties.$carousel_slider = $carousel_slider; 
properties.$first_pane = $first_pane; 

Giả sử cả hai đều đúng (tôi chưa thử nghiệm), đó là một cuộc gọi khó. Tôi nghĩ tôi thích phương pháp tiếp cận của Matthew Flaschen hơn, vì đoạn mã này chứa đựng một cấu trúc gần giống với tuyên bố đối tượng hơn. Cuối cùng cũng chỉ có một biến được tạo. Tuy nhiên, có rất nhiều this trong đó, có vẻ lặp đi lặp lại - mặc dù đó có thể chỉ là giá phải trả.

+1

OP: Nhân bản không nhất thiết phải được xác định theo thứ tự thời gian. Chúng tôi cố gắng chỉ mọi thứ trở lại các câu hỏi với các câu trả lời chi tiết và mở rộng hơn, với mục tiêu là chỉ ra một câu hỏi * kinh điển *. Tuy nhiên, đây không phải là một mục tiêu dễ dàng. Đánh dấu một câu hỏi như thế này là trùng lặp không phải là một dấu hiệu chống lại nó. Câu hỏi của bạn sẽ xuất hiện trên các công cụ tìm kiếm với các thuật ngữ khác nhau và nếu những câu trả lời này không giải quyết được giải pháp thì câu hỏi khác (rộng hơn) có thể. – CodeMouse92

+0

Case-in-point, tôi là tác giả của câu hỏi kinh điển và nhiều câu hỏi tập trung hơn, hẹp hơn đang được đánh dấu là bản sao của nó, để thu hút khách truy cập trang web hướng tới các câu trả lời hoàn chỉnh nhất. Tự hào - câu hỏi "trùng lặp" của bạn đang giúp bạn. :) – CodeMouse92

+0

Cảm ơn bạn đã làm rõ @ JasonMc92, điều đó có ý nghĩa. Sẽ xóa bản cập nhật của tôi. – Bungle

Trả lời

42

Không có đối tượng literals (this có cùng giá trị trong quá trình xây dựng chữ mà nó đã thực hiện trước đó). Nhưng bạn có thể làm

var carousel = new (function() 
{ 
     this.$slider = $('#carousel1 .slider'); 
     this.panes = this.$slider.children().length; 
})(); 

Điều này sử dụng đối tượng được tạo từ một hàm tạo ẩn danh.

Lưu ý rằng $sliderpanes là công khai, do đó có thể được truy cập như carousel.$slider vv

+0

Đây thực chất là một phiên bản chi tiết hơn của ví dụ thứ hai của OP. – casablanca

+1

@casablanca, không thực sự. Anh ta hỏi, "Có cách nào để các thuộc tính của một đối tượng tham chiếu tới các thuộc tính khác của cùng một đối tượng, trong khi đối tượng đó vẫn đang được khai báo không?", Và đó chính xác là cái này. Với ví dụ của tôi, 'carousel' có thể sử dụng các thuộc tính đã được xác định trước đó, nhưng nó không thể truy cập từ bên ngoài cho đến khi nó được xây dựng hoàn toàn. Với mã của mình, đó không phải là trường hợp. Và nó * không * sử dụng 'this' (mà OP nói anh ta muốn), thay vì phải lặp lại' carousel'. Ông nói rằng ông đang lên kế hoạch bổ sung thêm nhiều tài sản, điều này có thể khiến cho phương pháp này ngắn hơn. –

+1

Tôi đoán bạn đúng về điều đó. – casablanca

17

Thật không may, không có. Cú pháp {} khởi tạo một đối tượng mới, nhưng cho đến khi đối tượng được tạo, nó không được gán cho biến số carousel. Ngoài ra, giá trị this chỉ có thể thay đổi do cuộc gọi hàm.Nếu "nhiều thuộc tính khác" của bạn tất cả sẽ chỉ phụ thuộc vào slider, thì bạn có thể thực hiện những việc như sau:

var slider = $('.slider'); 
var carousel = { 
    panes: slider.children.length(), 
    something: slider.something_else, 
    // ... 
}; 
carousel.slider = slider; 
+0

Cảm ơn, casablanca! Tôi thích cách tiếp cận của bạn đối với các trường hợp khi hầu hết các thuộc tính của đối tượng chỉ dựa vào một hoặc hai biến khác. Đối với trường hợp sử dụng của tôi, thật không may, đó không phải là trường hợp, vì vậy tôi nghĩ rằng cách tiếp cận của Matthew Flaschen kết thúc được thanh lịch hơn một chút. Cảm ơn một lần nữa. – Bungle

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