首先介绍一下此篇随笔的主角:

  Object.getOwnPropertyDescriptor 和 Object.getOwnPropertyDescriptors

  通过这两个api,可以访问除 null 以外任何对象的属性。

  来看一个事实:

    var obj = { x : 1 }

    console.log( obj.x )  //  1

  通过小圆点访问的真的是 x 的值吗?你可以将小圆点看成一个运算符,访问到的永远是存取器属性内部的value值 或者 get 方法的返回值。

  前面我在一篇随笔中说到函数对象是存储在堆内存中的数据,而数字 1 明显应该是存在栈内存中的数据,难不成还会从堆内存中分配出一个地址指向栈内存?显然只有从栈定位到堆这种单向定位比较合理,那么是否 1 是一个对象的一部分呢? 是的,x 是另一个堆地址,开辟了一块空间,存储着存取器属性这个对象。

    Object.getOwnPropertyDescriptor( obj , 'x' )

    // { value: 1 , configurable: true , enumerable: true, writable: true }

  不难发现通过小圆点访问这个属性,实际上访问的是存取器属性的 value 值,其他三个属性见名知义,configurable控制着另外两个属性的修改权限,这里的 writable 简单理解就是说是否可以修改 x 的值,x 表示什么? 上面已经说到是堆内存的另一个地址,可以理解为是一个对象,因此不要误解为 value 的值,当然,这已经是最后一层存取器属性了,存取器的存取器属性如果有的话,那可能就不是我等能见到的底层了。。

  说了这么多,我们来实验一下,使得 obj 这个变量无法再指向另一个地址,也可以理解成 obj 这个对象的内容无法被改变:

  Object.defineProperty( window, 'obj', { writable: false } )

  obj = {}  // error

  知道了存取器属性的存在,我们能发现许多有意思的现象:

  var fn = new Function ;

  Object.getOwnPropertyDescriptor( fn , 'prototype' ) //{ writable: true , ... }

  Object.getOwnPropertyDescriptor( Object , 'prototype' ) //{ writable: false , ... }

  Object.getOwnPropertyDescriptor( Object.prototype , 'valueOf' ) //{ writable: true , ... }

  也就是说普通函数的原型地址是可以移动的,而内嵌的函数原型地址则不可以更改,但可以修改原型里的某些方法,这些都需要本文开头提到的两个 api 去鉴别。

  事实上,在存储器属性内除了这四个属性,还有可能具有 getter 和 setter 方法,但 value 属性和 get 方法不能同时存在:

  var a = { x:1 }
  Object.defineProperty( a , 'x' , {
    get ( ){
    return this.tmp
  },
    set ( val ){
    val > 0 ? this.tmp = val : this.tmp = 0
  }})
  a.x = 5 ;
  console.log( a.x )  // 5 
  a.x = -5 ;
  console.log( a.x ) // 0
 
  这里还有一点要注意的是, get 和 set 方法在存取器属性外的用法有所不同。
 

  

JavaScript 之存取器属性的更多相关文章

  1. 对象存取器属性:getter和setter

    在一个对象中,操作其中的属性或方法,通常运用最多的就是读(引用)和写了,譬如说o.a,这就是一个读的操作,而o.b = 1则是一个写的操作.事实上在除ie外最新主流浏览器的实现中,任何一个对象的键值都 ...

  2. js篇之对象数据属性与存取器属性

    在ECMAScript中,对象属性值可以用一个或两个方法代替,这两个方法就是getter和setter.由getter与与setter定义的属性叫做‘存取器属性’.当程序查询存取器属性的值时,js调用 ...

  3. JavaScript对象访问器属性

    对象访问器就是setter和getter,他们的作用就是 提供另外一种方法来获取或者设置对象的属性值, 并且在获取和设置的时候,可以用一定的其他操作. 看下面代码: <script> va ...

  4. 给内置对象或自定义对象添加存取器属性(getter setter)的方法总结

    funct = { get: function() { return this._x }, set: function(value) { this._x = value } } function Ob ...

  5. JavaScript对象中的属性(可写,可配置,可枚举,value,getter,setter)

    JavaScript中,对象包括3个特性,分别为,可扩展性,class标识符,属性. 如果对象的可扩展性为false,则不可为对象动态的添加属性.   对象包含分为存取器属性和值属性.存取属性为 {g ...

  6. JavaScript基础之对象属性的检测和枚举

    属性检测 对象作为属性的集合,属性又包括自有属性和继承属性: 检测方法: \__   in运算符: \__ var obj = { x:1 } console.log( 'toString' in o ...

  7. JavaScript 属性类型(数据属性和访问器属性)

    数据属性 数据属性包含一个数据值的位置.在这个位置可以读取和写入值.数据属性有 4 个描述其行为的特性. [[Configurable]]:表示能否通过 delete 删除属性从而重新定义属性,能否修 ...

  8. JavaScript 数据属性和访问器属性

    在JavaScript中对象被定义为"无序属性的集合,其属性可以包含基本值.对象或函数."通俗点讲,我们可以把对象理解为一组一组的名值对,其中值可以是数据或函数. 创建自定义对象通 ...

  9. javascript对象属性——数据属性和访问器属性

    ECMA-262第五版在定义时,描述了属性property的各种特征,定义这些特性是为了实现javascript引擎用的,为了表示该特性是内部值,规范把它们放在了两对儿方括号中,例如[[Enumera ...

随机推荐

  1. Saiku Table展示数据合并bug修复(二十五)

    Saiku Table展示数据合并bug修复 Saiku以table的形式展示数据,如果点击了 非空的字段 按钮,则会自动进行数据合并,为空的数据行以及数据列都会自动隐藏掉. 首先我们应该定位问题: ...

  2. shell 下生成使用UUID

    #!/bin/bash psd="/proc/sys/kernel/random/uuid" echo $(cat $psd)UUID=$(cat /proc/sys/kernel ...

  3. Vscode下的Markdown的基本使用

    1.Vscode默认支持Markdown语法,只需要安装相应的扩展插件,Markdown Preview enhanced. 2.安装完插件后,在Vscode上新建一个文件,然后将文件的语言模式设置为 ...

  4. 浅析android系统设计中的回调思想

    一.为何写作本文  在慢慢深入接触android开发的过程中,我越来越发现android中(至少应用曾的开发)用到了很多回调的思想.比如activity的生命周期,fragment的生命周期,皆是回调 ...

  5. ECharts柱状图

    首先我们要先去Echarts 官网 根据自己需要的版本进行下载下载 下载完成后,我们在项目中引入echarts 随后创建容器来存放我们要添加的柱状图 容器创建完毕我们需要在js中设置他的属性和值 此配 ...

  6. Kubernetes 常用命令

    文章摘自:https://blog.csdn.net/felix_yujing/article/details/51622132 1 查看类命令--- # 查看集群信息 kubectl cluster ...

  7. react Hooks

    useEffect 1.useEffect是didMount和didUpdate和willUnmount三个函数的集合 2.useEffec(fun):fun会在每次组件render之后执行,而fun ...

  8. intellij idea 程序包不可见问题

    刚用intellij idea不久,出现了个程序包不可见的问题. 原因:jdk9的问题,用的是jdk9就会出现这个问题. 解决办法:把jsk9换成jdk1.8就能解决.

  9. SQLServer数据库

    分离数据库:右键数据库→任务→分离数据库→确定 附加数据库:数据库右键→任务→附加→选择要附加的dlf文件→附加 导出SQL脚本步骤:右键数据库→任务→生成脚本→高级→要编写脚本的数据的类型→架构和数 ...

  10. Lvs Dr 模式配置

    1.Dr 安装 ipvsadm # yum -y install ipvsadm # lsmod | grep ip_vs    #检查ipvs模块是否加载进系统.把ipvs模块加载进系统,需要我们执 ...