Câu hỏi Đặt giá trị thông số mặc định cho hàm JavaScript


Tôi muốn một hàm JavaScript có các đối số tùy chọn mà tôi đặt mặc định, được sử dụng nếu giá trị không được xác định. Trong Ruby bạn có thể làm như sau:

def read_file(file, delete_after = false)
  # code
end

Điều này làm việc trong JavaScript?

function read_file(file, delete_after = false) {
  // Code
}

2022
2018-05-21 20:07


gốc




Các câu trả lời:


Từ ES6 / ES2015, các tham số mặc định nằm trong đặc tả ngôn ngữ.

function read_file(file, delete_after = false) {
  // Code
}

chỉ hoạt động.

Tài liệu tham khảo: Tham số mặc định - MDN

Các tham số hàm mặc định cho phép các tham số chính thức được khởi tạo với các giá trị mặc định nếu không có giá trị hoặc là chưa xác định được thông qua.

Bạn cũng có thể mô phỏng mặc định có tên thông số qua phá hoại:

// the `= {}` below lets you call the function without any parameters
function myFor({ start = 5, end = 1, step = -1 } = {}) { // (A)
    // Use the variables `start`, `end` and `step` here
    ···
}

ES2015 trước,

Có rất nhiều cách, nhưng đây là phương pháp ưa thích của tôi - nó cho phép bạn vượt qua bất cứ điều gì bạn muốn, bao gồm cả sai hoặc null. (typeof null == "object")

function foo(a, b) {
  a = typeof a !== 'undefined' ? a : 42;
  b = typeof b !== 'undefined' ? b : 'default_b';
  ...
}

2937
2018-05-21 20:10



Bạn cũng có thể đóng gói nó như vậy: function defaultFor(arg, val) { return typeof arg !== 'undefined' ? arg : val; } và sau đó bạn có thể gọi nó là a = defaultFor(a, 42); - Camilo Martin
@SiPlus và bạn có thêm lỗi tham chiếu miễn phí trong khi cố gắng sử dụng undefined objects: p Ngay cả khi nó có thể hoạt động với một số trình duyệt và có thể nhanh hơn, null vẫn là một đối tượng và undefined là tham chiếu đến kiểu nguyên thủy đang cố gắng nói rằng không có gì ở đây, thậm chí không null. Xem ở đây, cả hai trường hợp trong nutshell: JavaScript / Tham chiếu / Global_Objects / không xác định. - Sampo Sarrala
nếu bạn kiểm tra thuộc tính của đối tượng, thì typeof là thừa. function foo(data) { var bar = data.bar !== undefined ? data.bar : 'default'; } Điều này sẽ không ném lỗi tham chiếu và ngắn gọn. - Dziamid
Tôi biết nó thực sự rất nhỏ, nhưng tôi không thích cách bạn chỉ định a = a và b = b khi các tham số đó không được xác định. Ngoài ra, toán tử bậc ba đó có điều kiện phức tạp một chút có thể khó đọc đối với các nhà duy trì trong tương lai. Tôi thích cú pháp sau: if (typeof a == 'undefined') a = 42 - không có bài tập không cần thiết và dễ đọc hơn một chút. - Daddy32
Có lý do gì để sử dụng không typeof? Nó có vẻ đơn giản hơn để làm a === undefined. Thêm vào đó, bạn sẽ gặp lỗi tham chiếu nếu bạn viết sai chính tả undefined so với đặt nó trong một chuỗi. - Abe Voelker


function read_file(file, delete_after) {
    delete_after = delete_after || "my default here";
    //rest of code
}

Điều này được gán cho delete_after giá trị của delete_after nếu nó không phải là falsey giá trị khác, nó gán chuỗi "my default here". Để biết thêm chi tiết, hãy xem Khảo sát của Doug Crockford về ngôn ngữ và kiểm tra phần về Toán tử.

Cách tiếp cận này không hoạt động nếu bạn muốn vượt qua falsey giá trị tức là false, null, undefined, 0 hoặc là "". Nếu bạn yêu cầu falsey các giá trị được truyền vào trong bạn sẽ cần phải sử dụng phương thức trong Câu trả lời của Tom Ritter.

Khi xử lý một số tham số cho một hàm, nó thường hữu ích để cho phép người tiêu dùng chuyển các đối số tham số vào một đối tượng và sau đó hợp nhất các giá trị này với một đối tượng có chứa các giá trị mặc định cho hàm

function read_file(values) {
    values = merge({ 
        delete_after : "my default here"
    }, values || {});

    // rest of code
}

// simple implementation based on $.extend() from jQuery
function merge() {
    var obj, name, copy,
        target = arguments[0] || {},
        i = 1,
        length = arguments.length;

    for (; i < length; i++) {
        if ((obj = arguments[i]) != null) {
            for (name in obj) {
                copy = obj[name];

                if (target === copy) {
                    continue;
                }
                else if (copy !== undefined) {
                    target[name] = copy;
                }
            }
        }
    }

    return target;
};

sử dụng

// will use the default delete_after value
read_file({ file: "my file" }); 

// will override default delete_after value
read_file({ file: "my file", delete_after: "my value" }); 

559
2018-05-21 20:09



Tôi thấy điều này là không đủ, bởi vì tôi có thể muốn đi sai. - Tom Ritter
Tôi thấy nó phù hợp với hầu hết các tình huống - Russ Cam
Điều này cũng không hoạt động đối với 0. :( - Alex Kahn
Nó không hoạt động với bất kỳ giá trị falsey nào - Russ Cam
Bởi vì nó không làm việc cho các giá trị falsey, nó có thể tạo ra một cơn ác mộng bảo trì. Một chút mã luôn luôn được chuyển qua các giá trị chân lý trước đó và đột nhiên thất bại vì một con chim ưng được truyền vào có lẽ nên tránh khi có một phương pháp mạnh mẽ hơn. - jinglesthula


Tôi tìm thấy một cái gì đó đơn giản như thế này để được nhiều hơn nữa ngắn gọn và dễ đọc.

function pick(arg, def) {
   return (typeof arg == 'undefined' ? def : arg);
}

function myFunc(x) {
  x = pick(x, 'my default');
} 

137
2018-05-21 20:18



Cập nhật: Nếu bạn đang sử dụng underscore.js tôi đã tìm thấy nó thậm chí còn tốt hơn để sử dụng _.defaults(iceCream, {flavor: "vanilla", sprinkles: "lots"});. Sử dụng không gian tên toàn cầu như được hiển thị trong câu trả lời này là bởi nhiều người được coi là một thực hành xấu. Bạn cũng có thể xem xét việc cuộn tiện ích của riêng bạn cho tác vụ phổ biến này (ví dụ: util.default(arg, "defaul value")) nếu không muốn sử dụng gạch dưới, nhưng tôi chủ yếu kết thúc bằng cách sử dụng dấu gạch dưới sớm hay muộn thì không có điểm nào trong việc phát minh lại bánh xe. - andersand
@andersand Tôi thích ý tưởng về một cái gì đó như util.default(arg, "defaul value"))  bạn hoặc @ tj111 có đăng tải một bản demo nhanh không? - JasonDavis
Tôi thực sự đề nghị này, tôi sử dụng nó và gọi nó là "por" viết tắt của "tham số hoặc" - super
Đừng nói typeof arg == 'undefined', thay vào đó hãy nói arg === undefined - OsamaBinLogin
@OsamaBinLogin những gì bạn nói là chính xác cho JS hiện tại - thử nghiệm cũ hơn vẫn tồn tại bởi vì trên một số trình duyệt, nó được sử dụng để có thể ghi đè lên undefined với một số giá trị khác, khiến cho thử nghiệm thất bại. - Alnitak


Trong ECMAScript 6 bạn sẽ thực sự có thể viết chính xác những gì bạn có:

function read_file(file, delete_after = false) {
  // Code
}

Điều này sẽ thiết lập delete_after đến false nếu nó không có mặt hoặc undefined. Bạn có thể sử dụng các tính năng ES6 như thế này ngay hôm nay với các transpilers như Babel.

Xem bài viết MDN để biết thêm thông tin.


54
2018-05-29 15:25



ECMAScript 6 Tôi cho rằng ... (Tôi đã tự sửa chữa nhưng tôi không thể chỉnh sửa <6 ký tự) - Zac
Đang chờ trình duyệt có được ECMAScript 6 - Adriano Resende
Babel sẽ chuyển nó thành cái gì? - harryg
@harryg: babeljs.io/repl/… - Felix Kling
Đây là bảng tương thích cho ES6 kangax.github.io/compat-table/es6/#default_function_parameters Thật không may cú pháp này chưa được hỗ trợ. - freemanoid


Giá trị tham số mặc định

Với ES6, bạn có thể làm một trong những thành ngữ phổ biến nhất trong JavaScript liên quan đến việc thiết lập một giá trị mặc định cho một tham số hàm. Cách chúng tôi đã làm điều này trong nhiều năm nên trông khá quen thuộc:

function foo(x,y) {
 x = x || 11;
 y = y || 31;
 console.log( x + y );
}
foo(); // 42
foo( 5, 6 ); // 11
foo( 5 ); // 36
foo( null, 6 ); // 17

Mẫu này được sử dụng nhiều nhất, nhưng rất nguy hiểm khi chúng tôi chuyển các giá trị như

foo(0, 42)
foo( 0, 42 ); // 53 <-- Oops, not 42

Tại sao? Bởi vì 0 is falsyvà vì vậy x || 11 results in 11, không phải là thông qua trực tiếp trong 0. Để sửa lỗi này, một số người thay vào đó sẽ viết kiểm tra chi tiết hơn như sau:

function foo(x,y) {
 x = (x !== undefined) ? x : 11;
 y = (y !== undefined) ? y : 31;
 console.log( x + y );
}
foo( 0, 42 ); // 42
foo( undefined, 6 ); // 17

bây giờ chúng ta có thể kiểm tra một cú pháp hữu ích được thêm vào ES6 để hợp lý hóa việc gán các giá trị mặc định cho các đối số bị thiếu:

function foo(x = 11, y = 31) {
 console.log( x + y );
}

foo(); // 42
foo( 5, 6 ); // 11
foo( 0, 42 ); // 42
foo( 5 ); // 36
foo( 5, undefined ); // 36 <-- `undefined` is missing
foo( 5, null ); // 5 <-- null coerces to `0`
foo( undefined, 6 ); // 17 <-- `undefined` is missing
foo( null, 6 ); // 6 <-- null coerces to `0`

x = 11 trong một khai báo hàm giống như x !== undefined ? x : 11 hơn thành ngữ phổ biến hơn nhiều x || 11

Biểu thức giá trị mặc định

Function giá trị mặc định có thể không chỉ đơn giản là giá trị như 31; chúng có thể là bất kỳ biểu thức hợp lệ nào, thậm chí là function call:

function bar(val) {
 console.log( "bar called!" );
 return y + val;
}
function foo(x = y + 3, z = bar( x )) {
 console.log( x, z );
}
var y = 5;
foo(); // "bar called"
 // 8 13
foo( 10 ); // "bar called"
 // 10 15
y = 6;
foo( undefined, 10 ); // 9 10

Như bạn có thể thấy, các biểu thức giá trị mặc định được đánh giá uể oải, nghĩa là chúng chỉ chạy khi và khi cần - tức là khi đối số của tham số bị bỏ qua hoặc không được xác định.

Biểu thức giá trị mặc định thậm chí có thể là lệnh gọi hàm nội tuyến - thường được gọi là Biểu thức hàm được gọi ngay lập tức (IIFE):

function foo( x =
 (function(v){ return v + 11; })( 31 )
) {
 console.log( x );
}
foo(); // 42

18
2017-10-15 17:58





giải pháp đó làm việc cho tôi trong js:

function read_file(file, delete_after) {
    delete_after = delete_after || false;
    // Code
}

8
2017-11-16 11:29



Chuyện gì sẽ xảy ra nếu delete_after Là 0 hoặc là null? Nó sẽ không hoạt động đúng cho những trường hợp này. - Dmitri Pavlutin
@StephanBijzitter nó chỉ có thể đúng trong một số trường hợp. Nhưng nếu bạn chỉ muốn các giá trị mặc định để bỏ đặt giá trị thì nó không hoạt động, vì 0 hoặc null! === false. - Rutrus
@Rutrus: Tôi không hiểu bất cứ điều gì bạn vừa nói. - Stephan Bijzitter
Thế còn delete_after = delete_after === undefined ? false : delete_after? - aashah7


Chỉ cần sử dụng so sánh rõ ràng với không xác định.

function read_file(file, delete_after)
{
    if(delete_after === undefined) { delete_after = false; }
}

6
2017-11-16 07:34





là một nhà phát triển C ++ thời gian dài (Rookie để phát triển web :)), khi tôi lần đầu tiên gặp tình huống này, tôi đã thực hiện việc gán tham số trong định nghĩa hàm, như được đề cập trong câu hỏi, như sau.

function myfunc(a,b=10)

Nhưng hãy cẩn thận rằng nó không hoạt động liên tục trên các trình duyệt. Đối với tôi nó làm việc trên chrome trên máy tính để bàn của tôi, nhưng đã không làm việc trên chrome trên Android. Tùy chọn an toàn hơn, như nhiều người đã đề cập ở trên là -

    function myfunc(a,b)
    {
    if (typeof(b)==='undefined') b = 10;
......
    }

Ý định cho câu trả lời này không phải là lặp lại các giải pháp tương tự, những gì người khác đã đề cập, nhưng để thông báo rằng việc gán tham số trong định nghĩa hàm có thể hoạt động trên một số trình duyệt, nhưng không dựa vào nó.


5
2018-05-19 06:40



Việc gán trong định nghĩa hàm cũng không hoạt động trong IE 11, đây là phiên bản IE mới nhất cho Windows 8.1. - DiMono
Trong trường hợp ai đó tự hỏi, function myfunc(a,b=10) là cú pháp ES6, có các liên kết đến các bảng tương thích trong các câu trả lời khác. - gcampbell


Là bản cập nhật ... với ECMAScript 6 bạn có thể CUỐI CÙNG đặt giá trị mặc định trong khai báo tham số hàm như sau:

function f (x, y = 7, z = 42) {
  return x + y + z
}

f(1) === 50

Được tham chiếu bởi - http://es6-features.org/#DefaultParameterValues


4
2017-10-06 16:16



Câu trả lời này không hữu ích vì nó là một bản sao - user