object in javascript

weixin_33807284發表於2017-09-21
  • 列舉物件屬性

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
})
  • 簡單模擬基於資料劫持的資料繫結

思考:

  1. 劫持的資料是用來繫結到模板上的 | {{ }} ng-bind
  2. 怎麼繫結,定義watcher監聽表示式值的變化,渲染dom
  3. 資料變了,怎麼通知watcher更新模 | setter劫持
  4. 誰來通知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後的輸出:
 >   初始的盧雲
     後來的盧雲
     [ '無雙連拳', '正十七', '無絕心法' ]
    

相關文章