访问器属性之getter、setter函数

访问器属性之getter、setter函数

本来这篇文章萌芽是打算和Vue数据绑定放在一起写的,但是在阅读源码过程中萌芽发现了一些理解上的偏差所以萌芽这里打算将这俩函数单独拎出来写一篇文章,要是想理解 Vue的响应式数据 到底是怎么实现的那么首先我们就要了解ECMAScript中的属性。在ECMAScript中有两种属性:数据属性 和 访问器属性这里萌芽主要讲的是访问器属性的getter、setter函数,别的先不多讲。

  • 在读取访问器属性时会调用getter函数,这个函数负责返回有效的值;
  • 在写入访问器属性的时会调用setter函数并且【传入新的值】,这个函数负责决定如何处理数据。

属性介绍

数据属性(负责读取写入的权限控制,该属性有四个行为特性)
[ Configurable ]:能否通过delete删除。默认true
[ Enumerable ]:能否通过for-in循环返回属性。默认true
[ Writable ]:能否修改属性的值。默认为true
[ Value ]:包含这个属性的数据值。默认为undefined

访问器属性(包含一对儿getter和setter函数,该属性也有四个特性)
[ Configurable ]:能否通过delete删除。默认true
[ Enumerable ]:能否通过for-in循环返回属性。默认true
[ Get ]:读取 属性时调用的函数。默认为undefined
[ Set ]:写入 属性时调用的函数。默认为undefined

有没有感觉很熟悉呀,没错vue的数据绑定就是通过getter和sette实现的!
既然我们知道有这么个东西啦那该怎么去使用呢?往下看O(∩_∩)O

定义属性

访问器属性是不可以直接定义的,所以我们要借助 Object.defineProperty() 方法来定义。
这个方法有三个参数,第一个参数表示要在谁上面定义,第二个参数是这个访问器方法的命名,第三个就是定义我们的访问器属性的定义啦~通过下面的代码可以看得出来,萌芽修改了这个访问器随后他执行了自己的get set方法。这里萌芽专门用了不同于key名来定义这个访问器命名,就是想提醒大家这个访问器方法不是绑定在参数上的而是绑定在这个对象上的

var user = {
    name: '萌芽子',
    age: 18
}

Object.defineProperty(user, 'userAge', {
    get: function () {
        return `${this.name},今年${this.age}岁`;
    },
    set: function (newValue) {
        this.age = newValue - 5;
    }
})

user.userAge = 20;
console.log(user)  //输出:{ name: '萌芽子', age: 15 }

get方法需要定义下返回的内容,默认是返回undefined,set这里是有一个参数的,这个参数是指新传进来的值。这俩函数其实不是必须的,你也可以不定义他们。不过若是想要修改的属性多了的话定义起来岂不是会很麻烦吗?咱们往下看!

定义多个属性

话接上文!于是乎ECMAScript 5 又定义了一个Object.defineProperties()方法来解决我们的问题啦~他可以通过描述符(方法的命名)一次定义多个属性。他的第一个参数和上一个方法一样,只不过第二个参数有所不同第二个参数是将上个方法的第二个第三个融为一体了。

var user = {
    name: '萌芽子',
    age: 18
}

Object.defineProperties(user, {
    userName: {
        get: function () {
            return this.name
        },
        set: function (newValue) {
            this.name = '聪明机智的' + newValue
        }
    },
    userAge: {
        get: function () {
            return this.age + '岁'
        },
        set: function (newValue) {
            this.age = newValue - 5;
        }
    }
})

user.userName = '萌芽芽';
user.userAge = 20;
console.log(user.userName)//输出:聪明机智的萌芽芽
console.log(user.userAge)//输出:15岁

当然你也可以这么整,效果也是相同的:

这个方法接收两个对象参数:第一个对象是要添加和修改其属性的对象,第二个对象的属性与第一个对象中要添加或修改的属性一一对应。                                    - 摘自《JavaScript高级设计程序》

萌芽踩坑记

之前萌芽一直都理解的是这个访问器是绑定在这个对象里面的key上面的,后来几次实现发现并非如此,这个访问器是直接绑定在对象上的,由于之前看的源码的命名是和key一样的所以萌芽就被误导了,也算是自己理解不够到位。这里再次提醒广大亲友们下次我们再看到Vue里面的 this.msg = 'XXX' 参数的时候他其实并非修改了这个msg,此时虽然有msg但是你并没有直接修改这个data中的msg,而是修改的这个data中绑定的名为‘msg’的访问器方法啊!被表面现象蒙蔽了双眼的我这次记住它了!

当这些数据改变时,视图会进行重渲染。值得注意的是只有当实例被创建时就已经存在于 data 中的属性才是响应式的。

Object.defineProperty(data, 'msg',{你修改的内容其实就是为了触发这玩意儿})

瞎聊两句

非常感谢您花时间阅读我的文章,如有不足还请多多指教!这里萌芽打算立个Flag,最近比较怠惰一个月都不一定写一篇的,所以萌芽决定以后每周最少发一篇总结!果然无论做什么还是贵在坚持鸭 ~ 每天进步一点点,加油!^_^

发布了46 篇原创文章 · 获赞 43 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Meng_ya_zi/article/details/105398145
今日推荐