Có cách nào để đặt thuộc tính mặc định của một đối tượng javascript như vậy không:
var emptyObj = {};
// do some magic
emptyObj.nonExistingAttribute // => defaultValue
IE có thể bị coi thường, Chrome Frame đã giúp tôi giải tỏa cơn đau đầu đó.
Có cách nào để đặt thuộc tính mặc định của một đối tượng javascript như vậy không:
var emptyObj = {};
// do some magic
emptyObj.nonExistingAttribute // => defaultValue
IE có thể bị coi thường, Chrome Frame đã giúp tôi giải tỏa cơn đau đầu đó.
Câu trả lời:
Kể từ khi tôi hỏi câu hỏi vài năm trước, mọi thứ đã tiến triển tốt.
Proxy là một phần của ES6. Ví dụ sau hoạt động trong Chrome, Firefox, Safari và Edge :
var handler = {
get: function(target, name) {
return target.hasOwnProperty(name) ? target[name] : 42;
}
};
var p = new Proxy({}, handler);
p.answerToTheUltimateQuestionOfLife; //=> 42
Đọc thêm trong tài liệu của Mozilla về Proxy .
Object.getEntrieskhông thể gọi được trên Proxy :(
Object.entries, bạn có thể sửa đổi trình xử lý để đặt thuộc tính khi chúng được truy cập. Thay đổi return target.hasOwnProperty(name) ? target[name] : 42;thành if (!target.hasOwnProperty(name)) target[name] = 42; return target[name];.
Không có cách nào để đặt điều này trong Javascript - trả về undefinedcho các thuộc tính không tồn tại là một phần của đặc tả Javascript cốt lõi. Xem cuộc thảo luận cho câu hỏi tương tự này . Như tôi đã đề xuất ở đó, một cách tiếp cận (mặc dù tôi thực sự không thể đề xuất nó) sẽ là xác định một getPropertyhàm toàn cục :
function getProperty(o, prop) {
if (o[prop] !== undefined) return o[prop];
else return "my default";
}
var o = {
foo: 1
};
getProperty(o, 'foo'); // 1
getProperty(o, 'bar'); // "my default"
Nhưng điều này sẽ dẫn đến một loạt mã không chuẩn mà người khác sẽ khó đọc và nó có thể gây ra những hậu quả không mong muốn ở những khu vực mà bạn mong đợi hoặc muốn một giá trị không xác định. Tốt hơn là chỉ cần kiểm tra khi bạn đi:
var someVar = o.someVar || "my default";
var someVar = o.someVar || "my default";sẽ có kết quả có thể không mong muốn khi o.someVar được điền nhưng đánh giá là false (ví dụ: null, 0, ""). someVar = o.someVar === undefined ? o.someVar : "my default";sẽ tốt hơn. Tôi thường sử dụng ||một mình khi mặc định cũng đánh giá là false. (e.g. o.someVar || 0 ')
nullhoặc falsetheo cách tương tự như một thuộc tính chưa được đặt, trong trường hợp này, điều này có nghĩa vụ kép. Tuy nhiên, lời cảnh báo là công bằng.
someVar = o.someVar === undefined ? "my default" : o.someVar;, chỉ có một vấn đề nhỏ nhưng nó ném cho tôi một chút khi tôi lần đầu tiên thử code của bạn ;-)
Sử dụng cấu trúc hủy (mới trong ES6)
Có tài liệu tuyệt vời của Mozila cũng như một bài đăng trên blog tuyệt vời giải thích cú pháp tốt hơn tôi có thể.
var emptyObj = {};
const { nonExistingAttribute = defaultValue } = emptyObj;
console.log(nonExistingAttribute); // defaultValue
Tôi có thể đổi tên biến này không? Chắc chắn rồi!
const { nonExistingAttribute: coolerName = 15} = emptyObj;
console.log(coolerName); // 15
Còn về dữ liệu lồng nhau? Mang nó vào!
var nestedData = {
name: 'Awesome Programmer',
languages: [
{
name: 'javascript',
proficiency: 4,
}
],
country: 'Canada',
};
var {name: realName, languages: [{name: languageName}]} = nestedData ;
console.log(realName); // Awesome Programmer
console.log(languageName); // javascript
Điều này chắc chắn nghe giống như cách sử dụng điển hình của các đối tượng dựa trên protoype:
// define a new type of object
var foo = function() {};
// define a default attribute and value that all objects of this type will have
foo.prototype.attribute1 = "defaultValue1";
// create a new object of my type
var emptyObj = new foo();
console.log(emptyObj.attribute1); // outputs defaultValue1
attribute1: defaultValue1là trên nguyên mẫu và console.log chỉ liệt kê các mục được đặt trên đối tượng cấp cao nhất, không phải trên nguyên mẫu. Nhưng, giá trị ở đó khi tôi console.log(emptyObj.attribute1)thể hiện.
JSON.stringify(emptyobj). Tôi đã buộc phải tạo một phương thức trả về tất cả các thuộc tính để phản hồi lại vấn đề này
mã của tôi là:
function(s){
s = {
top: s.top || 100, // default value or s.top
left: s.left || 300, // default value or s.left
}
alert(s.top)
}
function foo( array $kwargs = array() ) { // Fill in defaults for optional keyworded arguments. $kwargs += array( 'show_user' => true, 'show_links' => false, ); ...
Cách tôi đạt được điều này là với object.assignhàm
const defaultProperties = { 'foo': 'bar', 'bar': 'foo' };
const overwriteProperties = { 'foo': 'foo' };
const newObj = Object.assign({}, defaultProperties, overwriteProperties);
console.log(defaultProperties); // {"foo": "bar", "bar": "foo"}
console.log(overwriteProperties); // { "foo": "foo" };
console.log(newObj); // { "foo": "foo", "bar": "foo" }
overwritePropertiescách chính xác là:const newObj = Object.assign({}, defaultProperties, overwriteProperties)
Tôi nghĩ rằng cách tiếp cận đơn giản nhất đang sử dụng Object.assign.
Nếu bạn có Lớp học này:
class MyHelper {
constructor(options) {
this.options = Object.assign({
name: "John",
surname: "Doe",
birthDate: "1980-08-08"
}, options);
}
}
Bạn có thể sử dụng nó như thế này:
let helper = new MyHelper({ name: "Mark" });
console.log(helper.options.surname); // this will output "Doe"
Tài liệu (với polyfill): https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
Hoặc bạn có thể thử cái này
dict = {
'somekey': 'somevalue'
};
val = dict['anotherkey'] || 'anotherval';
String()sửa chữa điều đó? Như trong:val = dict[String('anotherkey')] || 'anotherval';
d = {x: 1, y: 0}sau đó d['y'] || 100và không nó sai lầm cho 100. Sau đó thử ý tưởng của bạn đó là d[String('y')] || 100- nó vẫn đúng cho 100 khi nó sẽ cho 0.
Đơn giản nhất trong tất cả các Giải pháp:
dict = {'first': 1,
'second': 2,
'third': 3}
Hiện nay,
dict['last'] || 'Excluded'
sẽ trả về 'Bị loại trừ', là giá trị mặc định.
dict = {'first': 0, 'second': 1, 'third': 2}
a.b.c.d. Nếu a, d hoặc c không được xác định, bạn sẽ gặp lỗi, nhưng bạn có thể làm được(((a || {}).b || {}).c || {}).d) || "default"
Đối với tôi, đây có vẻ là cách đơn giản và dễ đọc nhất để làm như vậy:
let options = {name:"James"}
const default_options = {name:"John", surname:"Doe"}
options = Object.assign({}, default_options, options)
Tôi đã xem một bài báo hôm qua đề cập đến một Object.__noSuchMethod__ tính: JavascriptTips Tôi chưa có cơ hội chơi với nó, vì vậy tôi không biết về hỗ trợ trình duyệt, nhưng có thể bạn có thể sử dụng nó theo cách nào đó?
Tôi ngạc nhiên là chưa ai đề cập đến toán tử bậc ba.
var emptyObj = {a:'123', b:'234', c:0};
var defaultValue = 'defaultValue';
var attr = 'someNonExistAttribute';
emptyObj.hasOwnProperty(attr) ? emptyObj[attr] : defaultValue;//=> 'defaultValue'
attr = 'c'; // => 'c'
emptyObj.hasOwnProperty(attr) ? emptyObj[attr] : defaultValue; // => 0
Bằng cách này, ngay cả khi giá trị của 'c' là 0, nó vẫn sẽ nhận được giá trị chính xác.
Object.withDefault = (defaultValue,o={}) => {
return new Proxy(o, {
get: (o, k) => (k in o) ? o[k] : defaultValue
});
}
o = Object.withDefault(42);
o.x //=> 42
o.x = 10
o.x //=> 10
o.xx //=> 42
Điều này thực sự có thể làm với Object.create. Nó sẽ không hoạt động đối với các thuộc tính "không được xác định". Nhưng đối với những cái đã được cho một giá trị mặc định.
var defaults = {
a: 'test1',
b: 'test2'
};
Sau đó, khi bạn tạo đối tượng thuộc tính, bạn sẽ làm điều đó với Object.create
properties = Object.create(defaults);
Bây giờ bạn sẽ có hai đối tượng trong đó đối tượng đầu tiên trống, nhưng nguyên mẫu trỏ đến defaultsđối tượng. Để kiểm tra:
console.log('Unchanged', properties);
properties.a = 'updated';
console.log('Updated', properties);
console.log('Defaults', Object.getPrototypeOf(properties));
Một cách tiếp cận sẽ là lấy một đối tượng mặc định và hợp nhất nó với đối tượng đích. Đối tượng đích sẽ ghi đè các giá trị trong đối tượng mặc định.
jQuery có .extend()phương thức thực hiện điều này. Tuy nhiên, jQuery là không cần thiết vì có các triển khai JS vani như có thể tìm thấy ở đây:
http://gomakethings.com/vanilla-javascript-version-of-jquery-extend/
Tôi đến đây để tìm giải pháp vì tiêu đề phù hợp với mô tả vấn đề của tôi nhưng nó không phải là thứ tôi đang tìm kiếm nhưng tôi đã có giải pháp cho vấn đề của mình (tôi muốn có một giá trị mặc định cho một thuộc tính sẽ là động như ngày ).
let Blog = {
title : String,
image : String,
body : String,
created: {type: Date, default: Date.now}
}
Đoạn mã trên là giải pháp mà cuối cùng tôi đã giải quyết.