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

  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. netty解码器详解(小白也能看懂!)

    什么是编解码器? 首先,我们回顾一下netty的组件设计:Netty的主要组件有Channel.EventLoop.ChannelFuture.ChannelHandler.ChannelPipe等. ...

  2. 常见的操作系统及linux发展史

    目前我们常见的操作系统有: 1> 桌面操作系统 Windows 系列 用户群体大 macOS 适合于开发人员 Linux 应用软件少 2> 服务器操作系统 Linux 安全.稳定.免费 占 ...

  3. jquery添加属性使用attr、prop。

    之前页面为标签添加属性都是使用的attr,删除使用removeAttr. 今天给checkbox添加checked属性时出现代码显示添加成功,但是页面不勾选内容. 后来查询发现checked是chec ...

  4. org.apache.commons.vfs 配置文件里面 密码包含 @

    登录ftp的用户名 sftpuser ,密码 @sftpuser 在配置文件里面 需要 把 @ 转义 成 %40 ftppath=sftp://sftpuser:%40sftpuser@127.0.0 ...

  5. selenium中iframe的切换

    #第一层是默认层, 第二层是新建标签的层,第三层是百度的那层from selenium import webdriverimport timedriver=webdriver.Chrome()driv ...

  6. mysql无法安装,报 The older version of MySQL Installer - Community cannot be removed. Contact your technical support group

    解决办法: C:\Users\Administrator>msiexec /i C:\Users\Administrator\Downloads\mysql-installer-web-comm ...

  7. 关于redis的安装

    下载redis 我这边下载redis4.0.1版本, 然后解压 然后执行yum -y install gcc gcc-c++ libstdc++-devel 然后cd //qbtapp/redis-4 ...

  8. 第三次scrum冲刺

    第三次冲刺  一.第三次冲刺任务 ! 在已有的基础上实现图书馆管理员对图书信息的查询以及对图书借阅情况的查询. 二.用户故事 本次的用户是图书馆的管理员 用户输入对应的管理员的账号和密码 用户选择图书 ...

  9. 通过ajax提交表单上传文件

    //这是看的大神的.//原地址:https://www.cnblogs.com/kissdodog/archive/2012/12/15/2819025.html $("#sub" ...

  10. Oracle CONNECT by 简单用法

    Oracle查询层级的  一个表里 通过一个parentid连接 select * FROM A_MERIATILA start with id=520 CONNECT by prior id=PAR ...