对象的属性来源和可访问性

488 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

前言

对象是我们编程中最常的数据类型,也是最重要的数据类型,一起来了解他吧。

属性的来源

静态属性

比如Object.assign, Array.from这类,就属于静态属性,直接调用即可。

实例属性

需要被实例化,之后可以调用的方法,主要又为两类:

  1. 函数作为构造函数的实例
function Person(name, age){    
    this.name = name;
    this.age = age;
    this.getName = function(){
        return name
    }
}

Person.prototype.getAge = function(){
    return this.age;
}

var person = new Person()

name 和 getName都是直属于person上,而不是其原型上。

  1. class实例
class Person {
    constructor(name, age){
        this.name = name
        this.age = age
    }
    
    getName = ()=> {
        return this.name
    }
    
    getAge(){
        return this.age
    }
}

getName就是实例属性

原型属性

同上面的代码, getAge就是原型上属性

Person.prototype.getAge = function(){
    return this.age;
}

下面的getAge就是原型上属性

class Person {
    constructor(name, age){
        this.name = name
        this.age = age
    }
    
    getName = ()=> {
        return this.name
    }
    
    getAge(){
        return this.age
    }
}

属性的可访问性

可以通过Object.defineProperty或者Object.defineProperties进行设置,设置的可选项如下:

  • configurable —— 如果设为true,则可以修改或删除属性。如果设为false,则不允许修改。
  • enumerable —— 如果设为true,则可在for-in循环对象属性时出现(我们很快会介绍for-in循环)。
  • value —— 指定属性的值,默认为undefined。
  • writable —— 如果设为true,则可通过赋值语句修改属性值。
  • get —— 定义getter函数,当访问属性时发生调用,不能与value与writable同时使用。
  • set —— 定义setter函数,当对属性赋值时发生调用,也不能与value与writable同时使用。

颇有一些AOP,原子编程的思想。 后来ES5加入了Extension,freeze, seal等快捷操作,均可以对等到这上面的操作来。

vue3前期监听数据变化的核心,也就是这个Object.defineProperty, 当然,平时我们用到不多,因为主要写业务。

如果是写工具库,那就尤其重要了。

比如做一个简单的数据验证:

var product = {
    price: 10
}

Object.defineProperty(product, 'price', {
    set(val){
        if(val<0){
            throw new Error("price 必须大于0");
        }
    }
})

product.price = -10

image.png

当然,ES6时代的到来,现在都流行Proxy来控制对象的访问了,目前Object.defineProperty系列的优势,可能就是兼容性吧,随着ES6逐渐普及,可能作用越来越小。

个人觉得,其还有一个优势,就是不想Proxy那样,返回的是一个新的对象,您说对吧。

小结

今天你收获了吗?