當我嘗試從 JavaScript 類建構式中呼叫函式時指定引數名稱時,我得到一個ReferenceError.
我將基于一個簡化的例子來展示這個問題:
假設我有一個像這樣的物件和方法:
class Person {
constructor(name, age) {
this.name = name,
this.age = age
}
addYear() {
this.age ;
}
changeName(newName) {
this.name = newName;
}
changeAge(newAge) {
this.age = newAge;
}
changeAgeAndName(newName, newAge) {
this.changeName(newName=newName);
this.changeAge(newAge=newAge);
}
}
如果我將它實體化,一切都可以正常作業,如果與它混合一點,這就是代碼和輸出:
let p1 = new Person('George', 20);
console.log(p1);
p1.changeName(newName='Robert');
console.log(p1);
p1.changeAgeAndName(newName='Joe', newAge=23);
console.log(p1);
Person { name: 'George', age: 20 }
Person { name: 'Robert', age: 20 }
Person { name: 'Joe', age: 23 }
現在,假設我想在建構式中使用 changeAgeAndName (指定變數的引數名稱):
constructor(name, age) {
this.changeAgeAndName(newName=name, newAge=age);
}
我收到一個錯誤:
this.changeAgeAndName(newName=name, newAge=age);
ReferenceError: newName is not defined
但如果我不指定引數名稱,一切都很好:
constructor(name, age) {
this.changeAgeAndName(name, age);
}
最終輸出:
Person2 { name: 'Mike', age: 40 }
如果我在建構式之外指定引數名稱,一切都很好。我喜歡在編碼時盡可能明確,所以我想知道我可能做錯了什么。另外,我很好奇也許是另一個奇怪的 JS 行為的例子。謝謝!
uj5u.com熱心網友回復:
當你打電話時:
p1.changeAgeAndName(newName='Joe', newAge=23);
你以為你在指定newName引數應該是'Joe'。您實際上在做的是隱式宣告一個新變數,將結果設定為“Joe”,并將字串“Joe”作為第一個引數傳遞給函式。該函式不關心引數位置以外的任何內容。
如果要為清楚起見命名變數,請執行以下操作:
changeAgeAndName({newName, newAge}) {
//...
}
并呼叫它:
this.changeAgeAndName({newName: 'Joe', newAge: '23'});
正如@NickParsons 所指出的,班級主體的所有部分都處于“嚴格模式”。請參閱https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode#strict_mode_for_classes
因此,您的 ReferenceError 是由您的隱式變數宣告(做newName='Joe')引起的,而沒有先用let newName. 嚴格模式下不允許隱式變數宣告。
uj5u.com熱心網友回復:
所以事實證明我實際上是在自欺欺人,問題超出了建構式和嚴格模式。問題是 JS 根本沒有命名引數(我應該知道這一點,但直到最近我才弄亂它)。引數仍將按照創建函式時宣告的默認順序讀取。我認為 JS 在呼叫函式時拒絕任何命名變數的嘗試會更好。這將提供清晰。
如果您想明確命名引數,解決方案是“引數破壞”,如下所述:Is there a way to provide named parameters in a function call in JavaScript?
感謝@Nick Parsons 和@Andrew Parks
uj5u.com熱心網友回復:
做:
p1.changeAgeAndName(newName,newAge)
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/529253.html
標籤:javascript哎呀
下一篇:一內一排序
