Đặt giá trị tham số mặc định cho hàm JavaScript


2367

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 (và bị bỏ qua nếu giá trị được thông qua). Trong Ruby bạn có thể làm như thế này:

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

Cái này có hoạt động với JavaScript không?

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

Câu trả lời:


3297

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.

Tham khảo: Thông số mặc định - MDN

Các tham số chức năng 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 không xác định nào được thông qua.

Bạn cũng có thể mô phỏng các tham số được đặt tên mặc định thông qua việc hủy bỏ :

// 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
    ···
}

Trước ES2015 ,

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 mọi thứ bạn muốn, kể cả sai hoặc không. ( typeof null == "object")

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

216
Bạn cũng có thể gói gọn 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

6
@SiPlus và bạn đã nhận được các lỗi tham chiếu bổ sung miễn phí trong khi thử sử dụng undefinedcác đối tượng: 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, nullvẫn là một đối tượng và undefinedđược tham chiếu đến loại nguyên thủy đang cố gắng nói rằng có Không có gì ở đây, thậm chí không null. Xem ở đây, cả hai trường hợp tóm tắt: JavaScript / Reference / Global_Objects / không xác định .
Sampo Sarrala - codidact.org

9
nếu bạn kiểm tra đối với tài sản của một đối tượng, thì đó typeoflà dự phòng. 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

10
Tôi biết điều đó thực sự nhỏ, nhưng tôi không thích cách bạn đang gán a = ab = bkhi các tham số đó không được xác định. Ngoài ra, toán tử ternary với một điều kiện hơi phức tạp có thể khó đọc cho các nhà bảo 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 cộng với một chút dễ đọc hơn.
Daddy32

12
Có bất kỳ lý do để sử dụ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ả undefinedso với đặt nó trong một chuỗi.
Abe Voelker

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

Điều này gán cho delete_aftergiá trị delete_afternếu nó không phải là giá trị falsey nếu không nó gán chuỗi "my default here". Để biết thêm chi tiết, hãy xem khảo sát về ngôn ngữ của Doug Crockford và xem phần về Người vận hành .

Cách tiếp cận này không làm việc nếu bạn muốn vượt qua trong một falsey giá trị tức là false, null, undefined, 0hoặc "". Nếu bạn yêu cầu các giá trị falsey được truyền vào, bạn sẽ cần 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 hàm, thường rất hữu ích khi cho phép người tiêu dùng truyền các đối số tham số trong một đối tượng và sau đó hợp nhất các giá trị này với một đối tượng 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" }); 

115
Tôi thấy điều này là không đủ, bởi vì tôi có thể muốn vượt qua sai.
Tom Ritter

52
Tôi thấy nó phù hợp với hầu hết các tình huống
Russ Cam

50
Bởi vì nó không hoạt động 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 được thông qua các giá trị trung thực 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 cách tiếp cận mạnh mẽ hơn.
jinglểula

1
Làm thế nào mà, trong trường hợp này, delete_afterkhông nhận được kết quả boolean của biểu thức delete_after || "my default value"?
xbonez

3
hoặc, bạn chỉ có thể mặc định với giá trị falsey - dù sao đó thường là mặc định tốt (ví dụ: sai cho bool, chuỗi rỗng cho chuỗi, 0 cho số, v.v.) - trong trường hợp đó không thực sự quan trọng thông qua.
Mark Brackett

150

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

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

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

6
Cập nhật: Nếu bạn đang sử dụng underscore.js, tôi thấy nó 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ư trong câu trả lời này được nhiều người coi là một thực tiễn xấu. Bạn cũng có thể cân nhắc việc sử dụng tiện ích của riêng mình cho tác vụ chung này (ví dụ: util.default(arg, "defaul value")nếu không muốn sử dụng dấu 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 dù sao cũng không có điểm nào trong việc phát minh lại bánh xe.
andersand

2
Tôi thực sự khuyên bạn nên dùng cái này, tôi sử dụng nó và gọi nó là "por", viết tắt của "tham số hoặc"
siêu

2
Đừng nói typeof arg == 'không xác định', thay vào đó hãy nói arg === không xác định
OsamaBinLogin

3
@OsamaBinLogin những gì bạn nói là chính xác đối với 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ó thể ghi đè lên undefinedmột số giá trị khác, khiến thử nghiệm thất bại.
Alnitak

2
@Alnitak: Vẫn có thể ghi đè undefined. Vì vậy, nó vẫn là một ý tưởng tốt để sử dụng typeof'undefined'.
LS

63

Trong ECMAScript 6, bạn thực sự 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ẽ được đặt delete_afterthành falsenế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 bộ chuyển mã như Babel .

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


1
ECMAScript 6 Tôi cho rằng ... (Tôi sẽ tự sửa nhưng tôi không thể chỉnh sửa <6 ký tự)
Zac

1
Chờ đợi trình duyệt nào nhận được ECMAScript 6
Adriano Resende

1
Babel sẽ chuyển cái này sang cái gì?
harryg


2
Dưới đây là bảng tương thích cho ES6 kangax.github.io/compat-table/es6/#default_feft_parameter Rất tiếc, cú pháp này chưa được hỗ trợ .
freemanoid

27

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

Với ES6, có lẽ bạn có thể thực hiện một trong những thành ngữ phổ biến nhất JavaScriptliên quan đến việc đặt giá trị mặc định cho tham số hàm. Cách chúng ta đã làm điều này trong nhiều năm sẽ 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 nguy hiểm khi chúng ta 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 falsy, và vì vậy x || 11 results in 11, không phải là trực tiếp được truyền vào 0. Để sửa lỗi gotcha này, một số người thay vào đó sẽ viết séc bằng lời nói như thế này:

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 tốt đẹp đượ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 = 11trong một khai báo hàm giống như x !== undefined ? x : 11thành ngữ phổ biến hơn nhiềux || 11

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

Functiongiá trị mặc định có thể không chỉ là các giá trị đơn giản 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á một cách lười biếng, có nghĩa là chúng chỉ chạy nếu và khi chúng cần - nghĩa là khi đối số của tham số bị bỏ qua hoặc không được xác định.

Một biểu thức giá trị mặc định thậm chí có thể là một lệnh gọi biểu thức 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

13

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

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

4
Điều gì xảy ra nếu delete_after0hoặc null? Nó sẽ không hoạt động chính xác cho những trường hợp này.
Dmitri Pavlutin

@StephanBijzitter nó chỉ đú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 các giá trị thì điều này không hoạt động, vì 0 hoặc null! === sai.
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

10

Chỉ cần sử dụng một 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; }
}

10

Tôi đặc biệt khuyên bạn nên hết sức thận trọng khi sử dụng các giá trị tham số mặc định trong javascript. Nó thường tạo ra lỗi khi sử dụng kết hợp với các chức năng bậc cao như forEach, map, và reduce. Ví dụ, hãy xem xét dòng mã này:

['1', '2', '3'].map(parseInt); // [1, NaN, NaN]

parseInt có một tham số thứ hai tùy chọn function parseInt(s, [radix=10]) nhưng ánh xạ các cuộc gọi parseIntvới ba đối số: ( phần tử , chỉ mụcmảng ).

Tôi đề nghị bạn tách các tham số cần thiết của bạn tạo thành các đối số có giá trị tùy chọn / mặc định. Nếu hàm của bạn có 1,2 hoặc 3 tham số bắt buộc mà không có giá trị mặc định nào có ý nghĩa, hãy biến chúng thành tham số vị trí cho hàm, mọi tham số tùy chọn sẽ tuân theo dưới dạng các thuộc tính được đặt tên của một đối tượng. Nếu hàm của bạn mất 4 hoặc nhiều hơn, có lẽ sẽ có ý nghĩa hơn khi cung cấp tất cả các đối số thông qua các thuộc tính của một tham số đối tượng.

Trong trường hợp của bạn tôi sẽ đề nghị bạn viết hàm của bạn DeleteFile như thế này: ( thay đổi nội dung cho mỗi instead 's bình luận ) ...

// unsafe
function read_file(fileName, deleteAfter=false) {
    if (deleteAfter) {
        console.log(`Reading and then deleting ${fileName}`);
    } else {
        console.log(`Just reading ${fileName}`);
    }
}

// better
function readFile(fileName, options) {
  const deleteAfter = !!(options && options.deleteAfter === true);
  read_file(fileName, deleteAfter);
}

console.log('unsafe...');
['log1.txt', 'log2.txt', 'log3.txt'].map(read_file);

console.log('better...');
['log1.txt', 'log2.txt', 'log3.txt'].map(readFile);

Chạy đoạn trích trên minh họa các mối nguy hiểm ẩn đằng sau các giá trị đối số mặc định cho các tham số không sử dụng.


1
"Giải pháp tốt hơn" này khá khó đọc. Tôi muốn đề nghị kiểm tra loại biến như typeof deleteAfter === 'bool'và ném Ngoại lệ khác. Ngoài ra, trong trường hợp sử dụng các phương thức như map / foreach, v.v. chỉ cần sử dụng chúng một cách thận trọng và bọc các hàm được gọi là hàm ẩn danh. ['1', '2', '3'].map((value) => {read_file(value);})
thay vì

Đó là một điểm hay. Tôi đã cố gắng tránh sử dụng các thư viện trong đoạn mã của mình, nhưng thành ngữ này khá lộn xộn trong javascript thuần túy. Cá nhân, tôi sẽ sử dụng getphương thức của lodash để truy xuất xóa Sau đó. Ném một ngoại lệ nếu typeof 'deleteAfter' !== 'bool'cũng có thể là một biện pháp thận trọng tốt. Tôi không thích thiết kế các phương pháp yêu cầu người gọi "thận trọng". Thận trọng là trách nhiệm của chức năng, không phải người gọi. Các hành vi kết thúc nên theo nguyên tắc ít bất ngờ nhất.
Doug Coburn

Tôi đồng ý, phương pháp đó không nên được viết theo cách, mà gọi nó, có thể phá vỡ hành vi của nó. Nhưng hãy nhớ rằng chức năng giống như mô hình và người gọi giống như bộ điều khiển. Mô hình nên chăm sóc xử lý dữ liệu. Hàm (phương thức) nên mong dữ liệu đó, có thể được truyền sai cách và xử lý nó. Đó là lý do tại sao kiểm tra loại tham số cộng với ném Ngoại lệ, là cách tốt nhất. Mặc dù nó phức tạp hơn. Nhưng nó vẫn có thể cứu bạn khỏi gãi đầu và tiếp tục hỏi ... TẠI SAO NÓ KHÔNG LÀM VIỆC?! và sau đó ... TẠI SAO NÓ ĐANG LÀM VIỆC?!
thay vì

9

Là một bản cập nhật ... với ECMAScript 6, bạn có thể HOÀN TOÀN đặt các giá trị mặc định trong các khai báo tham số hàm như vậy:

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

f(1) === 50

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


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

8

là một nhà phát triển C ++ lâu năm (Rookie để phát triển web :)), khi tôi gặp tình huống này lần đầu tiên, tôi đã thực hiện 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 nhất quán trên các trình duyệt. Đối với tôi, nó hoạt động trên chrome trên máy tính để bàn của tôi, nhưng không hoạt động 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 đừng dựa vào nó.


3
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

1
Trong trường hợp bất kỳ ai thắc mắc, 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

7

Đối với bất kỳ ai quan tâm đến việc có mã làm việc trong Microsoft Edge, không sử dụng mặc định trong các tham số chức năng.

function read_file(file, delete_after = false) {
    #code
}

Trong ví dụ đó, Edge sẽ đưa ra lỗi "Mong đợi ')'"

Để sử dụng

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

Kể từ ngày 8 tháng 8 năm 2016, đây vẫn là một vấn đề


4

Theo cú pháp

function [name]([param1[ = defaultValue1 ][, ..., paramN[ = defaultValueN ]]]) {
   statements
}

bạn có thể xác định giá trị mặc định của các tham số chính thức. và cũng kiểm tra giá trị không xác định bằng cách sử dụng hàm typeof .


4
function helloWorld(name, symbol = '!!!') {
    name = name || 'worlds';
    console.log('hello ' + name + symbol);
}

helloWorld(); // hello worlds!!!

helloWorld('john'); // hello john!!!

helloWorld('john', '(>.<)'); // hello john(>.<)

helloWorld('john', undefined); // hello john!!!

helloWorld(undefined, undefined); // hello worlds!!!

4

Sử dụng điều này nếu bạn muốn sử dụng ECMA6cú pháp mới nhất :

function myFunction(someValue = "This is DEFAULT!") {
  console.log("someValue --> ", someValue);
}

myFunction("Not A default value") // calling the function without default value
myFunction()  // calling the function with default value

Nó được gọi là default function parameters. Nó 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 không xác định nào được thông qua. LƯU Ý : Nó không hoạt động với Internet Explorer hoặc các trình duyệt cũ hơn.

Để tương thích tối đa có thể sử dụng này:

function myFunction(someValue) {
  someValue = (someValue === undefined) ? "This is DEFAULT!" : someValue;
  console.log("someValue --> ", someValue);
}

myFunction("Not A default value") // calling the function without default value
myFunction()  // calling the function with default value

Cả hai hàm đều có hành vi giống hệt nhau vì mỗi ví dụ này dựa trên thực tế là biến tham số sẽ là undefinednếu không có giá trị tham số nào được truyền khi gọi hàm đó.


LƯU Ý: như @BlackBeard nói, hàm (param = value) KHÔNG hoạt động với IE. Sử dụng phiên bản tương thích.
MagicLAMP

4

ES6: Như đã đề cập trong hầu hết các câu trả lời, trong ES6, bạn có thể chỉ cần khởi tạo một tham số cùng với một giá trị.


ES5: Hầu hết các câu trả lời đưa ra không đủ tốt cho tôi vì có những lúc tôi có thể phải chuyển các giá trị falsey như 0, nullundefinedcho một hàm. Để xác định xem một tham số không được xác định bởi vì đó là giá trị tôi đã truyền thay vì không xác định do chưa được xác định. Tôi làm điều này:

function foo (param1, param2) {
   param1 = arguments.length >= 1 ? param1 : "default1";
   param2 = arguments.length >= 2 ? param2 : "default2";
}

3

function throwIfNoValue() {
throw new Error('Missing argument');
}
function foo(argValue = throwIfNoValue()) {
return argValue ;
}

Ở đây foo () là một hàm có tham số có tên argValue. Nếu chúng ta không chuyển bất cứ thứ gì trong hàm gọi ở đây, thì hàm throw IfNoValue () sẽ được gọi và kết quả trả về sẽ được gán cho đối số duy nhất argValue. Đây là cách gọi hàm có thể được sử dụng làm tham số mặc định. Điều này làm cho mã đơn giản hơn và dễ đọc hơn.

Ví dụ này đã được lấy từ đây


3

Nếu bạn đang sử dụng, ES6+bạn có thể đặt tham số mặc định theo cách sau:

function test (foo = 1, bar = 2) {
  console.log(foo, bar);
}

test(5); // foo gets overwritten, bar remains default parameter

Nếu bạn cần ES5cú pháp, bạn có thể làm theo cách sau:

function test(foo, bar) {
  foo = foo || 2;
  bar = bar || 0;
  
  console.log(foo, bar);
}

test(5); // foo gets overwritten, bar remains default parameter

Trong cú pháp trên ORtoán tử được sử dụng. Các ORnhà điều hành luôn luôn trả về giá trị đầu tiên nếu điều này có thể được chuyển đổi sang truenếu không nó sẽ trả về giá trị righthandside. Khi hàm được gọi không có đối số tương ứng, biến tham số ( bartrong ví dụ của chúng tôi) được đặt undefinedbởi công cụ JS. undefinedSau đó được chuyển đổi thành false và do đó ORtoán tử trả về giá trị 0.


3

Có, sử dụng tham số mặc định được hỗ trợ đầy đủ trong ES6 :

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

hoặc là

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

nhưng trước ES5 bạn có thể dễ dàng làm điều này:

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

Điều đó có nghĩa là nếu giá trị ở đó, hãy sử dụng giá trị, nếu không, sử dụng giá trị thứ hai sau khi ||hoạt động, điều tương tự ...

Lưu ý: cũng có một sự khác biệt lớn giữa những giá trị đó nếu bạn chuyển một giá trị cho ES6, ngay cả giá trị đó là sai lệch , sẽ được thay thế bằng giá trị mới, một cái gì đó giống như nullhoặc ""... nhưng chỉ một ES5 sẽ được thay thế nếu chỉ có giá trị được chuyển là sự thật, đó là vì cách ||làm việc ...


2

Nếu vì một lý do nào đó, bạn không sử dụng ES6 và đang sử dụng lodashở đây là một cách ngắn gọn để tham số chức năng mặc định thông qua _.defaultTophương thức:

var fn = function(a, b) {
  a = _.defaultTo(a, 'Hi')
  b = _.defaultTo(b, 'Mom!')

  console.log(a, b)
}

fn()                 // Hi Mom!
fn(undefined, null)  // Hi Mom!
fn(NaN, NaN)         // Hi Mom!
fn(1)                // 1 "Mom!"
fn(null, 2)          // Hi 2
fn(false, false)     // false false
fn(0, 2)             // 0 2
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Cái nào sẽ đặt mặc định nếu giá trị hiện tại là NaN , null hoặc không xác định


1

Âm thanh của tương lai

Trong tương lai, bạn sẽ có thể "trải" một đối tượng sang đối tượng khác (hiện tại là vào năm 2019 KHÔNG được Edge hỗ trợ !) - trình diễn cách sử dụng điều đó cho các tùy chọn mặc định đẹp bất kể thứ tự:

function test(options) {
    var options = {
       // defaults
       url: 'defaultURL',
       some: 'somethingDefault',
       // override with input options
       ...options
    };
    
    var body = document.getElementsByTagName('body')[0];
    body.innerHTML += '<br>' + options.url + ' : ' + options.some;
}
test();
test({});
test({url:'myURL'});
test({some:'somethingOfMine'});
test({url:'overrideURL', some:'andSomething'});
test({url:'overrideURL', some:'andSomething', extra:'noProblem'});

Tham chiếu MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/S rải_syntax

... Trong khi đó, những gì Edge DOES hỗ trợ là Object.assign () (IE thì không, nhưng tôi thực sự hy vọng chúng ta có thể bỏ lại IE :))

Tương tự bạn có thể làm

    function test(options) {
        var options = Object.assign({
           // defaults
           url: 'defaultURL',
           some: 'somethingDefault',
        }, options); // override with input options
        
        var body = document.getElementsByTagName('body')[0];
        body.innerHTML += '<br>' + options.url + ' : ' + options.some;
    }
    test();
    test({});
    test({url:'myURL'});
    test({some:'somethingOfMine'});
    test({url:'overrideURL', some:'andSomething'});
    test({url:'overrideURL', some:'andSomething', extra:'noProblem'});

EDIT: Do nhận xét về constcác tùy chọn - vấn đề với việc sử dụng các tùy chọn không đổi trong phần còn lại của hàm thực sự không phải là bạn không thể làm điều đó, chỉ là bạn không thể sử dụng biến không đổi trong khai báo của chính nó - bạn sẽ có để điều chỉnh việc đặt tên đầu vào thành một cái gì đó như

function test(input_options){
   const options = {
     // defaults
     someKey:    'someDefaultValue',
     anotherKey: 'anotherDefaultValue',

     // merge-in input options
     ...input_options
   };

   // from now on use options with no problem
}

Vấn đề là bạn bình thường không bao giờ muốn làm điều đó vì điều này sẽ gán lại các tùy chọn đã được xác định nhưng bạn có thể sử dụng nó với một var khác sẽ hợp pháp.
thẳng thắn

kiểm tra chức năng (tùy chọn) {/ * Tùy chọn được xác định, nó sẽ báo lỗi nếu bạn sử dụng tùy chọn const = {} ngay bây giờ * /}
frank-dspeed

không phải là toàn cục khi bạn tạo một hàm và bạn chuyển vào dưới dạng tùy chọn tên đối số thì bên trong các tùy chọn hàm được xác định bên trong hàm (opt) {} opt được xác định bạn không thể sử dụng const opt ​​bên trong hàm đó thì điều này là xấu vì bạn làm xác định lại biến nếu bạn làm điều đó thường xuyên và có vẻ như mô hình chung của bạn đây là một vấn đề
thẳng thắn

@ google-frank-dspeed ah, ý bạn là bạn không thể làm gì function(opt){ const opt = /*some merging*/; }? Điều đó chắc chắn sẽ không hoạt động vì bạn sẽ sử dụng constbiến trước khi nó được khai báo - bạn sẽ phải điều chỉnh -function test(input_opt){ const opt = { someKey: 'someDefaultValue', ...input_opt} }
jave.web 16/12/19

@ google-frank-dspeed dù sao nhiều người mới cũng có thể sẽ thắc mắc về điều này, vì vậy tôi đã thêm mã hướng dẫn để chỉnh sửa :) vì vậy cảm ơn bạn đã chỉ ra điều đó cho người khác :)
jave.web 16/12/19

1

Chỉ để thể hiện các kỹ năng của tôi (lol), hàm trên có thể được viết ngay cả khi không có các đối số được đặt tên như dưới đây:

ES5 trở lên

function foo() {
    a = typeof arguments[0] !== 'undefined' ? a : 42;
    b = typeof arguments[1] !== 'undefined' ? b : 'default_b';
    ...
}

ES6 trở lên

function foo(...rest) {
    a = typeof rest[0] !== 'undefined' ? a : 42;
    b = typeof rest[1] !== 'undefined' ? b : 'default_b';
    ...
}

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

Mã sau có thể hoạt động trong tình huống này bao gồm ECMAScript 6 (ES6) cũng như các phiên bản trước đó.

function read_file(file, delete_after) {
    if(delete_after == undefined)
        delete_after = false;//default value

    console.log('delete_after =',delete_after);
}
read_file('text1.txt',true);
read_file('text2.txt');

vì giá trị mặc định trong các ngôn ngữ hoạt động khi giá trị tham số của hàm bị bỏ qua khi gọi, trong JavaScript, nó được gán cho không xác định . Cách tiếp cận này không hấp dẫn về mặt lập trình nhưng có khả năng tương thích ngược .


0

Vâng, điều này được gọi là một tham số mặc định

Các tham số chức năng 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 không xác định nào được thông qua.

Cú pháp:

function [name]([param1[ = defaultValue1 ][, ..., paramN[ = defaultValueN ]]]) {
   statements
}

Sự miêu tả:

Các tham số của hàm mặc định thành không xác định Tuy nhiên, trong các tình huống có thể hữu ích để đặt một giá trị mặc định khác. Đây là nơi các tham số mặc định có thể giúp đỡ.

Trước đây, chiến lược chung để đặt mặc định là kiểm tra các giá trị tham số trong phần thân của hàm và gán giá trị nếu chúng không được xác định. Nếu không có giá trị nào được cung cấp trong cuộc gọi, giá trị của nó sẽ không được xác định. Bạn sẽ phải đặt kiểm tra có điều kiện để đảm bảo tham số không được xác định

Với các tham số mặc định trong ES2015, việc kiểm tra trong thân hàm không còn cần thiết nữa. Bây giờ bạn có thể chỉ cần đặt một giá trị mặc định trong đầu hàm.

Ví dụ về sự khác biệt:

// OLD METHOD
function multiply(a, b) {
  b = (typeof b !== 'undefined') ?  b : 1;
  return a * b;
}

multiply(5, 2); // 10
multiply(5, 1); // 5
multiply(5);    // 5


// NEW METHOD
function multiply(a, b = 1) {
  return a * b;
}

multiply(5, 2); // 10
multiply(5, 1); // 5
multiply(5);    // 5

Các ví dụ cú pháp khác nhau:

Đệm không xác định so với các giá trị giả mạo khác:

Ngay cả khi giá trị được đặt rõ ràng khi gọi, giá trị của đối số num là giá trị mặc định.

function test(num = 1) {
  console.log(typeof num);
}

test();          // 'number' (num is set to 1)
test(undefined); // 'number' (num is set to 1 too)

// test with other falsy values:
test('');        // 'string' (num is set to '')
test(null);      // 'object' (num is set to null)

Đánh giá tại thời điểm cuộc gọi:

Đối số mặc định được đánh giá tại thời điểm cuộc gọi, vì vậy không giống như một số ngôn ngữ khác, một đối tượng mới được tạo mỗi khi hàm được gọi.

function append(value, array = []) {
  array.push(value);
  return array;
}

append(1); //[1]
append(2); //[2], not [1, 2]


// This even applies to functions and variables
function callSomething(thing = something()) {
 return thing;
}

function something() {
  return 'sth';
}

callSomething();  //sth

Các tham số mặc định có sẵn cho các tham số mặc định sau này:

Params đã gặp có sẵn cho các tham số mặc định sau này

function singularAutoPlural(singular, plural = singular + 's',
                        rallyingCry = plural + ' ATTACK!!!') {
  return [singular, plural, rallyingCry];
}

//["Gecko","Geckos", "Geckos ATTACK!!!"]
singularAutoPlural('Gecko');

//["Fox","Foxes", "Foxes ATTACK!!!"]
singularAutoPlural('Fox', 'Foxes');

//["Deer", "Deer", "Deer ... change."]
singularAutoPlural('Deer', 'Deer', 'Deer peaceably and respectfully \ petition the government for positive change.')

Các chức năng được xác định bên trong cơ thể chức năng:

Được giới thiệu trong Gecko 33 (Firefox 33 / Thunderbird 33 / SeaMonkey 2.30). Các hàm được khai báo trong thân hàm không thể được tham chiếu bên trong các tham số mặc định và ném ReferenceError (hiện là TypeError trong SpiderMonkey, xem lỗi 1022967). Các tham số mặc định luôn được thực hiện trước, khai báo hàm bên trong thân hàm đánh giá sau đó.

// Doesn't work! Throws ReferenceError.
function f(a = go()) {
  function go() { return ':P'; }
}

Các tham số không có mặc định sau các tham số mặc định:

Trước Gecko 26 (Firefox 26 / Thunderbird 26 / SeaMonkey 2.23 / Firefox OS 1.2), đoạn mã sau dẫn đến SyntaxError. Điều này đã được sửa trong lỗi 777060 và hoạt động như mong đợi trong các phiên bản sau. Các tham số vẫn được đặt từ trái sang phải, ghi đè các tham số mặc định ngay cả khi có các tham số sau này mà không có mặc định.

function f(x = 1, y) {
  return [x, y];
}

f(); // [1, undefined]
f(2); // [2, undefined]

Tham số hủy cấu trúc với gán giá trị mặc định:

Bạn có thể sử dụng gán giá trị mặc định với ký hiệu gán hủy

function f([x, y] = [1, 2], {z: z} = {z: 3}) {
  return x + y + z;
}

f(); // 6

0

Chỉ cần một cách tiếp cận khác để đặt tham số mặc định là sử dụng sơ đồ đối tượng của đối số, thay vì đối số trực tiếp. Ví dụ,

const defaultConfig = {
 category: 'Animals',
 legs: 4
};

function checkOrganism(props) {
 const category = props.category || defaultConfig.category;
 const legs = props.legs || defaultConfig.legs;
}

Bằng cách này, thật dễ dàng để mở rộng các đối số và không lo lắng về độ dài đối số không khớp.


-1

Câu trả lời là có. Trong thực tế, có nhiều ngôn ngữ hỗ trợ các tham số mặc định. Python là một trong số đó:

def(a, enter="Hello"):
   print(a+enter)

Mặc dù đây là mã Python 3 do dấu ngoặc đơn, các tham số mặc định trong các hàm cũng hoạt động trong JS.

Ví dụ, và trong trường hợp của bạn:

function read_file(file, deleteAfter=false){
  console.log(deleteAfter);
}

read_file("test.txt");

Nhưng đôi khi bạn không thực sự cần các tham số mặc định.

Bạn chỉ có thể xác định biến ngay sau khi bắt đầu hàm, như thế này:

function read_file(file){
  var deleteAfter = false;
  console.log(deleteAfter);
}

read_file("test.txt");

Trong cả hai ví dụ của tôi, nó trả về cùng một thứ. Nhưng đôi khi chúng thực sự có thể hữu ích, như trong các dự án rất tiên tiến.

Vì vậy, kết luận, các giá trị tham số mặc định có thể được sử dụng trong JS. Nhưng nó gần giống như việc xác định một biến ngay sau khi bắt đầu hàm. Tuy nhiên, đôi khi chúng vẫn rất hữu ích. Như bạn có thể nhận thấy, các giá trị tham số mặc định mất ít hơn 1 dòng mã so với cách tiêu chuẩn xác định tham số ngay sau khi bắt đầu hàm.

EDIT: Và điều này là siêu quan trọng! Điều này sẽ không hoạt động trong IE. Xem tài liệu . Vì vậy, với IE, bạn phải sử dụng phương thức "xác định biến ở đầu hàm". Các tham số mặc định sẽ không hoạt động trong IE.


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.