Vue中使用n-avatar時要注意的點
屬性描述符
只針對name這個屬性,假如物件有其他屬性的話則不受影響,如果呼叫Object.defineProperty()時,如果這三個引數都不指定,那麼全部預設為false
let obj = {}
Object.defineProperty(obj, 'name', {
configurable: false, //是否可以配置屬性描述符
writable: false, //是否可以改寫屬性的值
enumerable: false, //控制屬性是否會出現在物件的列舉當中(遍歷的到不)
value: '屬性識別符號' //屬性的值
})
不變性
有時候需要建立一個變數是不變的,不只是對於簡單值,引用值裡面的值也不變。也就是說可以用屬性描述符,即configurable:false
Object.defineProperty(person, "age", {
configurable: false,
writable: false,
value:2,
});
禁止擴充套件
如何禁止一個物件再新增新的屬性,可以使用Object.preventExtensions(obj)
密封
假如想一個物件即不能新增新屬性也不能改變既有屬性的值,可以一個一個的給物件屬性新增屬性描述符,也可以使用Object.seal(obj)去建立一個密封物件,它會自動完成上面的功能。
凍結
Object.freeze(obj)會建立一個凍結物件,這個方法實際上會呼叫seal。
如果在專案進行優化的時候,有一個數組或者object,並且確信資料不會修改,可以使用凍結讓效能大幅提升
JavaScript的getter和setter
【GET】
get,獲取的意思,平常對於物件中資料的獲取大部分是直接呼叫,如下
let a = {}
a.name = '9527'
console.log(a.name); //9527
但是在使用.的時侯預設呼叫了物件的內建get函式去獲取物件的值,獲取的路徑是先在物件中查詢是否具有同名的屬性,沒有的話就會去原型鏈上查詢,如果一直沒有則返回undefined
let a = {}
a.__proto__.age = 21
console.log(a.age); //21
console.log(a.name); //undefined
但是當自己在物件中聲明瞭get函式後並且沒有宣告set函式,則不能再對物件的屬性進行修改
let a = {
name: 'sifan',
get name() {
return this.name
},
}
console.log(a.name) //undefined
a.name = 'sifan111'
console.logo(a.name) //undefined
所以當設定了get或set函式後,js就不在關心value和writable屬性,而是去監聽get、set函式還有configurable與enumerable屬性
【Getter】
當我們獲取一個物件的屬性的時候,就會呼叫getter函式,但首先要給物件設定getter,否則返回undefined,當給物件定義了getter和setter後,js也會忽略value和writable,而且優先順序比get高
let a = {
get name() {
console.log('呼叫了自己的方法get');
return this._name
},
set name(val) {
console.log('呼叫自己的方法set');
this._name = val
}
}
Object.defineProperty(a,'name',{
get: function() {
console.log('呼叫getter函式');
return this._name + 'getter'
}
})
console.log(a.name) //undefinedgetter
a.name = '11
console.log(a.name) //11getter
【setter】
當需要修改一個屬性的值的時候,會觸發set函式,並且傳入一個引數val就是想要賦予的值
【vue】
在Vue2中,Object.defineProperty是vue的響應式和雙向繫結的主要實現底層,在set中監聽屬性的改變,並呼叫notify()函式去通知使用到這個函式的節點的值更新為最新的值,如下部分程式碼:
Object.defineProperty(data, key, {
enumerable: true,
configurable: true,
get() {
if (Dep.target) {
dep.addSub(Dep.target);
}
return val;
},
set(newValue) {
if (val === newValue) {
return;
}
// 資料發生變化 dep通知wather更新
val = newValue;
dep.notify();
},
});
undefined型別的值和找不到值返回的undefined的區別
可以判斷這個屬性是否存在物件或者原型鏈上
使用in操作符
in操作符可以檢查屬性是否存在於物件及其物件的原型鏈之中
const obj = {
a: undefined,
};
obj.__proto__.c=undefined
console.log(obj.a);//undefined
console.log(obj.b);//undefined
console.log("a" in obj);//true
console.log("b" in obj);//false
console.log("c" in obj);//true
但是in操作符不能判斷一個值是否在陣列中,因為in操作符檢測的式容器內的某個屬性名,對於陣列來說包含的屬性名是下標
let arr = ['a', 'b', 'c']
console.log('a' in arr); //false
console.log(1 in arr); //true
使用hasOwnProperty()
與in操作符不同的是,hasOwnProperty()是不會檢測原型鏈,也就是隻查詢自己本身的屬性,而且也是檢測屬性名
const obj = {
a: undefined,
};
obj.__proto__.c=5
console.log(obj.hasOwnProperty("a"));//true
console.log(obj.hasOwnProperty("b"));//false
console.log(obj.hasOwnProperty("c"));//false
let arr = ['a', 'b', 'c']
console.log(arr.hasOwnProperty('a')); //false
console.log(arr.hasOwnProperty(1)); //true
遍歷
for...in可以遍歷物件屬性列表,注意:即可以遍歷陣列,也可以遍歷物件
const array = [1, 2, 3, 4];
for (let i in array) {
console.log(i, array[i]);
}
// 0 1
// 1 2
// 2 3
// 3 4
for...of可以遍歷陣列值列表,注意:只能遍歷陣列,不能遍歷物件
const array = [1, 2, 3, 4];
for (let index of array) {
console.log(index);
}
// 1
// 2
// 3
// 4
輔助迭代器
ES5中的一些陣列的輔助迭代器:
forEach
const array = [1, 2, 3, 4]
array.forEach((item) => {
console.log(item); //1,2,3,4
});
some
array.some((item) => {
console.log(item); //1,2,3,4
return false
});
every
array.every((item) => {
console.log(item); //1,2,3,4
return true
});
some和every的區別:some是當返回值有一個是返回true就結束遍歷,every是當返回值有一個是false的時候結束遍歷
forEach沒有返回值
手動遍歷
使用es6的symbol型別,Symbol.iterator可以獲取物件的內部屬性,然後可以帶有next()方法,返回的是一個{value, done},value是值,done是當前是否到了底部
const array = [1, 2, 3, 4];
const it = array[Symbol.iterator]();
console.log(it.next());// {value: 1, done: false}
console.log(it.next());// {value: 2, done: false}
console.log(it.next());// {value: 3, done: false}
console.log(it.next());// {value: 4, done: false}
console.log(it.next());// {value: undefined, done: true}