Chuyển đổi Javascript so với if Khác khác nếu khác Khác


143

Tôi có một vài câu hỏi:

  1. Có sự khác biệt về hiệu suất trong JavaScript giữa một switch câu lệnh và câu lệnh if...elsekhông?
  2. Nếu vậy tại sao?
  3. Là hành vi switchif...elsekhác nhau trên các trình duyệt? (FireFox, IE, Chrome, Opera, Safari)

Lý do cho câu hỏi này là dường như tôi có hiệu suất tốt hơn trên một switchcâu lệnh với khoảng 1000 trường hợp trong Firefox.


Rất tiếc, đây không phải là mã của tôi, Javascript đang được tạo ra từ các thư viện được biên dịch và tôi không có quyền truy cập vào mã. Phương thức tạo javascript được gọi là

CreateConditionals(string name, string arrayofvalues, string arrayofActions)

lưu ý arrayofvalueslà một danh sách được phân tách bằng dấu phẩy.

những gì nó tạo ra là

function [name] (value) {
  if (value == [value from array index x]) {
     [action from array index x]
  }
}

Lưu ý: where [name]= tên được truyền vào chức năng máy chủ

Bây giờ tôi đã thay đổi đầu ra của hàm được chèn vào TextArea, viết một số mã JavaScript để phân tích cú pháp và chuyển đổi nó thành một tập hợp case câu lệnh.

cuối cùng tôi chạy chức năng và nó chạy tốt nhưng hiệu năng khác nhau trong IE và Firefox.


1
Tôi sẽ đề xuất một mẫu mã để kiểm tra những gì tối ưu. Ý tôi là, phải có một lý do bạn hỏi điều này, phải không?
jcolebrand

Vui lòng gửi những gì bạn đang làm, bởi vì có rất ít trường hợp trong kinh nghiệm lâu dài của tôi mà tôi muốn nói rằng một tuyên bố chuyển đổi 100 trường hợp hoặc một loạt 100 phần nếu / khác là một ý tưởng tốt.
Mũi nhọn

Xin lỗi các bạn không phải 100 tuổi mà là hàng ngàn điều kiện
John Hartsock

2
Mọi người, cảm ơn vì đầu vào. Nhưng vấn đề của tôi không thực sự là sự khác biệt giữa các bức tượng if và swith. Đó là mã chạy bên trong câu lệnh. +1 cho tất cả các bạn vì sự giúp đỡ của bạn. Xin lỗi vì sự bất tiện này. Đôi khi bạn chỉ cần nói chuyện với người khác để tìm giải pháp.
John Hartsock

Câu trả lời:


113

Trả lời chung chung:

  1. Vâng, thông thường.
  2. Xem thêm thông tin tại đây
  3. Có, bởi vì mỗi công cụ có một công cụ xử lý JS khác nhau, tuy nhiên, khi chạy thử nghiệm trên trang web bên dưới, công tắc luôn luôn thực hiện if, otherif trên một số lượng lớn các lần lặp.

Địa điểm thi


1
Nếu bạn muốn có một TLDR khi sử dụng mà điều kiện ở đây là một liên kết trực tiếp tới một phân khúc trong bài viết đề cập rằng: oreilly.com/server-administration/excerpts/even-faster-websites/...
edhedges

2
@Tommy Bài viết hay, cảm ơn đã chia sẻ. Tuy nhiên, bài viết nói rằng có một sự khác biệt hiệu năng không đáng kể giữa switchvà các if/thencâu lệnh trong JS. Bài viết nói rằng điều này là do switchtối ưu hóa tại chỗ và các cách khác nhau của các công cụ JS khác nhau. Trích dẫn:Since most JavaScript engines don’t have such optimizations, performance of the switch statement is mixed.
Jasper

3
Có bất cứ điều gì định lượng được hiển thị trong mô tả này? Nó đọc giống như rất nhiều phỏng đoán "thực hành tốt nhất / tối ưu hóa sớm". Nó cũng được viết 7 năm trước, vì vậy tối ưu hóa javascript đã thay đổi rất nhiều trong thời gian này. Trong các ngôn ngữ được biên dịch, sự khác biệt hiệu suất giữa ba thao tác này là "hầu như không bao giờ đủ quan trọng để quan tâm". Đừng bận tâm đến việc tối ưu hóa những thứ sẽ không ảnh hưởng đến hiệu suất thực tế. Tối ưu hóa khả năng đọc.
Thomson Comer

3
@ Mẹ ơi « Xem thêm thông tin ở đây » cung cấp 404, có gì ở đó?
LogicDaemon

2
@LogicDaemon - IIRC là một liên kết đến một số hộp văn bản oRielly được đưa vào một số cân nhắc / thảo luận về hiệu suất của JS
Tommy

61

Đôi khi tốt hơn là không sử dụng. Ví dụ: trong tình huống "điều phối", Javascript cho phép bạn thực hiện mọi việc theo một cách hoàn toàn khác:

function dispatch(funCode) {
  var map = {
    'explode': function() {
      prepExplosive();
      if (flammable()) issueWarning();
      doExplode();
    },

    'hibernate': function() {
      if (status() == 'sleeping') return;
      // ... I can't keep making this stuff up
    },
    // ...
  };

  var thisFun = map[funCode];
  if (thisFun) thisFun();
}

Thiết lập phân nhánh đa chiều bằng cách tạo một đối tượng có rất nhiều lợi thế. Bạn có thể thêm và xóa chức năng một cách linh hoạt. Bạn có thể tạo bảng công văn từ dữ liệu. Bạn có thể kiểm tra nó theo chương trình. Bạn có thể xây dựng các trình xử lý với các chức năng khác.

Có thêm chi phí của một lệnh gọi hàm để tương đương với "trường hợp", nhưng lợi thế (khi có nhiều trường hợp) của tra cứu băm để tìm hàm cho một khóa cụ thể.


2
Chiến lược của bạn là tốt và tôi sử dụng nó thường xuyên. Nhưng như được chỉ ra bởi @Michael Geary stackoverflow.com/a/45336805/5936119 , biến bản đồ phải được khai báo bên ngoài bối cảnh công văn nếu không nó sẽ luôn được đánh giá lại.
Daniel Santana

@DanielSantana đúng nhưng tôi nghi ngờ rằng nó đắt tiền đáng kể. Cụ thể, một khi một chức năng được phân tích cú pháp ban đầu, bản thân không cần phải được tạo lại, vì văn bản là tĩnh.
Mũi nhọn

18

Sự khác biệt hiệu suất giữa a switchif...else if...elsenhỏ, về cơ bản chúng làm cùng một công việc. Một điểm khác biệt giữa chúng có thể tạo ra sự khác biệt là biểu thức cần kiểm tra chỉ được đánh giá một lần trong một switchlần if. Nếu tốn kém để đánh giá biểu thức, thì việc thực hiện một lần dĩ nhiên nhanh hơn thực hiện một trăm lần.

Sự khác biệt trong việc thực hiện các lệnh đó (và tất cả các tập lệnh nói chung) khác nhau khá nhiều giữa các trình duyệt. Chúng ta thường thấy sự khác biệt hiệu năng khá lớn cho cùng một mã trong các trình duyệt khác nhau.

Vì bạn khó có thể thực hiện kiểm tra tất cả mã trong tất cả các trình duyệt, bạn nên tìm mã phù hợp nhất với những gì bạn đang làm và cố gắng giảm số lượng công việc được thực hiện thay vì tối ưu hóa cách thực hiện.


7
  1. Nếu có sự khác biệt, nó sẽ không bao giờ đủ lớn để được chú ý.
  2. Không có
  3. Không, tất cả đều hoạt động giống hệt nhau.

Về cơ bản, sử dụng bất cứ điều gì làm cho mã dễ đọc nhất. Chắc chắn có những nơi mà một hoặc các cấu trúc khác làm cho sạch hơn, dễ đọc hơn và dễ bảo trì hơn. Điều này quan trọng hơn nhiều có lẽ là tiết kiệm một vài nano giây trong mã JavaScript.


5
Đặc biệt trong javascript, ngữ nghĩa và khả năng đọc (và do đó là khả năng duy trì) tạo ra bất kỳ sự khác biệt hiệu suất cục bộ nào giữa if..elseswitchgây ra bởi sự kết hợp giữa phần cứng máy tính và hệ điều hành phiên bản trình duyệt duy nhất.
bóng

2
Tôi không biết nếu tôi đồng ý, nó thực sự có thể được chú ý nếu nó được sử dụng trong một vòng lặp với một cơ sở dữ liệu lớn, đi ngang qua một cái cây, v.v.
ghoppe

2
Tôi chắc chắn không đồng ý. khi các ứng dụng web ngày càng phức tạp hơn, sự khác biệt này có thể có ý nghĩa đối với ứng dụng và có thể thay đổi tùy thuộc vào trình duyệt.
joshvermaire

7
Điều quan trọng là viết mã sạch, có thể bảo trì. Khi một vấn đề hiệu suất được nhìn thấy - hồ sơ. Sau đó xác định mã nào để sửa. Đừng hy sinh khả năng bảo trì cho các vấn đề hiệu suất giả định.
Jon Benedicto

3
'nếu khác nếu khác ...' là O (n), trong khi 'chuyển đổi' là O (1) hoặc O (log (n)). Làm thế nào bạn có thể nói một cách trung thực sự khác biệt không bao giờ có thể đủ lớn? Có hàng triệu trường hợp chuyển đổi (dễ dàng có thể nếu mã được tạo) và bạn chắc chắn sẽ nhận thấy nó để nói ít nhất.
Dragonroot

6

Khác với cú pháp, một chuyển đổi có thể được thực hiện bằng cách sử dụng một cây tạo ra nó O(log n), trong khi một if / khác phải được thực hiện với một O(n)cách tiếp cận thủ tục. Thông thường, cả hai đều được xử lý theo thủ tục và sự khác biệt duy nhất là cú pháp, và hơn nữa nó thực sự có vấn đề - trừ khi bạn tĩnh nhập 10k trường hợp nếu / khác?


7 năm sau ... Tôi không thấy cách thực hiện cây có thể, ngoại trừ trong trường hợp giá trị trường hợp số không đổi).
Ed Staub

4

Câu trả lời của Point gợi ý việc sử dụng một đối tượng theo nghĩa đen thay thế cho switchhoặc if/ else. Tôi cũng thích cách tiếp cận này, nhưng mã trong câu trả lời sẽ tạo ra một mapđối tượng mới mỗi khi dispatchhàm được gọi:

function dispatch(funCode) {
  var map = {
    'explode': function() {
      prepExplosive();
      if (flammable()) issueWarning();
      doExplode();
    },

    'hibernate': function() {
      if (status() == 'sleeping') return;
      // ... I can't keep making this stuff up
    },
    // ...
  };

  var thisFun = map[funCode];
  if (thisFun) thisFun();
}

Nếu mapchứa một số lượng lớn các mục, điều này có thể tạo ra chi phí đáng kể. Chẳng hạn, tốt hơn là chỉ thiết lập bản đồ hành động một lần và sau đó sử dụng bản đồ đã được tạo mỗi lần:

var actions = {
    'explode': function() {
        prepExplosive();
        if( flammable() ) issueWarning();
        doExplode();
    },

    'hibernate': function() {
        if( status() == 'sleeping' ) return;
        // ... I can't keep making this stuff up
    },
    // ...
};

function dispatch( name ) {
    var action = actions[name];
    if( action ) action();
}

3

Có sự khác biệt về hình thức trong Javascript giữa câu lệnh chuyển đổi và nếu ... khác nếu .... khác không?

Tôi không nghĩ vậy, switchlà hữu ích / ngắn nếu bạn muốn ngăn ngừa nhiều if-elseđiều kiện.

Là hành vi của chuyển đổi và nếu ... khác nếu ... khác trên các trình duyệt? (FireFox, IE, Chrome, Opera, Safari)

Hành vi là giống nhau trên tất cả các trình duyệt :)


5
switch is useful/short if you want prevent multiple if-else conditions.Vâng thưa ông, bài viết tuyệt vời.
NiCk Newman

1
  1. Làm việc có thể dẫn đến một số khác biệt rất nhỏ trong một số trường hợp, nhưng cách xử lý vẫn phụ thuộc vào trình duyệt nên không đáng bận tâm
  2. Do cách chế biến khác nhau.
  3. Bạn không thể gọi nó là trình duyệt nếu hành vi sẽ khác đi

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.