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

  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. 【转载】IP地址和子网划分学习笔记之《子网掩码详解》

    原文地址: https://blog.51cto.com/6930123/2112748 一.子网掩码 IP地址是以网络号和主机号来标示网络上的主机的,我们把网络号相同的主机称之为本地网络,网络号不相 ...

  2. Oracle 11g 单实例到单实例OGG同步实施文档-EXPDP初始化

    Oracle 11g 单实例到单实例OGG同步实施文档-EXPDP初始化 2018-06-07 00:446470原创GoldenGate 作者: leo 本文链接:https://www.cndba ...

  3. ES6 中 Promise

    在说Promise之前我们先简单说一下什么是同步异步? 同步(Sync):所谓同步,就是发出一个功能调用时,在没有得到结果之前,该调用就不返回或继续执行后续操作. 异步(Async):异步与同步相对, ...

  4. win10 安装mysql 8.0.12

    按照CSDN以及博客园的其他教程, 之前安装过几次都有或多或少的bug 主要安装步骤: 1.配置my.ini文件 2.管理员进入终端, 切换到.../bin目录下进行操作 3.指令操作: 1) mys ...

  5. Cronolog日志分割、定时清理

    阿里云发送短信提示服务器磁盘占用到80%警报短信 经过排查发现tomcat日志文件达到10个多G,手动删除过久的日志文件后恢复到50% 但是catalina.out文件还有6个G 解决方法 一.安装C ...

  6. ssh整合报错严重: Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'xxx'

    错误描述:eclipse整合ssh的时候 报不能创建名字为xxx的对象 信息: Destroying singletons in org.springframework.beans.factory.s ...

  7. Android中的几个基本常用控件

    Android 中常用的几大UI控件 1. TextView : 用于在界面中显示一段文本信息 <TextView android:id="@+id/text_view" / ...

  8. Java 平时作业六

    编写一个 Java 应用程序,使用 Java 的输入输出流技术将 Input.txt 的内容(Input.txt 为文本 文件)逐行读出, 每读出一行就顺序为其添加行号(从 1 开始,逐行递增),并写 ...

  9. Jest 学习笔记(一)之matchers

    Jest官网地址 Jest是专门被facebook用于测试包括React应用在内的所有javascript代码,Jest旨在提供一个综合的零计算的测试体验. 因为没有找到文档,基于我个人的经验,Jes ...

  10. Python基础(切片,list循环,元组)

    list和字符串循环: 切片:list取值的一种方式,同样适用于字符串(因为字符串也有下标) 不可变类型:元组,字符串