列舉物件屬性
for....in
列舉obj的可列舉屬性,包括自身和原型鏈上的
object.keys()
只列舉物件本身的可列舉屬性
建立物件的幾種方式
物件字面量
const pre='test'
const obj= {
"name":"luyun",
[pre+'prop']:"wu shuang lian quan"
}
通過建構函式
const obj= new Object()
const d = new Date()
Object.create()
以指定的物件作為原型來建立物件
var Animal = {
type: 'Invertebrates', // Default value of properties
displayType: function() { // Method which will display type of Animal
console.log(this.type);
}
};
var animal1 = Object.create(Animal);
//這樣,animal1的原型就是Animal了
如何判斷物件是否是空物件
typeof {} == 'object'
Object.keys({}).length===0
物件屬性的描述符
屬性的描述符分data描述符和訪問描述符,對一個屬性來說,只能存在一種描述符,configurable、enumerable是公共的。
const users={
a:'luyun'
}
Object.getOwnPropertyDescriptor( users, "a" );
//資料描述符
// {
// value: 2,
// writable: true,
// enumerable: true,
// configurable: true
// }
writeable 是否可以修改
enumable 是否可列舉,出現在 for in 中
configurable 是否可通過defineProperty()來修改描述符,為false時,屬性不能刪除
Getter、Setter
當你給一個屬性定義getter、setter或者兩者都有時,這個屬性會被定義為“訪問描述符”(和“資料描
述符”相對)
const users={
'name':'luyun'
}
Object.defineProperty(users,'kongfu',{
get:function(){
return '正十七'
},
enumerable:true
})
簡單模擬基於資料劫持的資料繫結
思考:
- 劫持的資料是用來繫結到模板上的 | {{ }} ng-bind
- 怎麼繫結,定義watcher監聽表示式值的變化,渲染dom
- 資料變了,怎麼通知watcher更新模 | setter劫持
- 誰來通知watcher | 釋出訂閱模式
首先封裝Object.defineProperty監聽屬性的變化
function observe(data) {
const keys = Object.keys(data)
keys.forEach(key => {
gs(data, key, data[key])
})
}
//劫持資料
function gs(obj, key, val) {
let originVal = val
const subpub = new Subpub()
Object.defineProperty(obj, key, {
configurable: true,
enumerable: true,
get() {
//這裡應該確定訂閱者是誰
Subpub.target && subpub.addWatcher()
return originVal
},
set(value) {
originVal = value
//訂閱了當前屬性的都要更新
subpub.notice()
}
})
}
釋出訂閱,需要知道哪些地方用到了當前屬性的值,在屬性值變化時,要更新這些地方
function Subpub() {
this.subList = [] //儲存訂閱某個屬性的訂閱者
}
Subpub.prototype.addSub = function (watcher) {
this.subList.push(watcher)
}
//通知訂閱者們,資料變化了,你們要各自行動了
Subpub.prototype.notice = function () {
this.subList.forEach(item => {
item.render()
})
}
Subpub.prototype.addWatcher = function () {
Subpub.target.addSubpub(this)
}
function Watcher(exp, fn) {
Subpub.target = this
this.exp = exp
//監聽的屬性的初始值
this.value = user[exp] //這裡寫死的user,應該是當前環境下的資料,比如angular中$scope
this.fn = fn
Subpub.target = null
}
Watcher.prototype.render = function () {
const oldValue = this.value
const newValue = user[this.exp]
this.fn(newValue, oldValue)
}
Watcher.prototype.addSubpub = function (subpub) {
subpub.addSub(this)
}
const user = {
name: '初始的盧雲',
kongfu: '無'
}
observe(user)
//這裡只是簡單的列印新值
new Watcher('name', function (newVal,old) {
console.log(old)
console.log(newVal)
})
new Watcher('kongfu', function (newVal) {
console.log(newVal)
})
user.name = "後來的盧雲"
user.kongfu=['無雙連拳','正十七', '無絕心法']
//設定name,kongfu後的輸出:
> 初始的盧雲
後來的盧雲
[ '無雙連拳', '正十七', '無絕心法' ]