0

0

JS添加getter+setter总结

php中世界最好的语言

php中世界最好的语言

发布时间:2018-06-12 09:36:22

|

2075人浏览过

|

来源于php中文网

原创

这次给大家带来JS添加getter+setter总结,JS添加getter+setter的注意事项有哪些,下面就是实战案例,一起来看一下。

定义 getter 与 setter

1.通过对象初始化器在创建对象的时候指明(也可以称为通过字面值创建对象时声明)

(function () {
  var o = {
    a : 7,
    get b(){return this.a +1;},//通过 get,set的 b,c方法间接性修改 a 属性
    set c(x){this.a = x/2}
  };
  console.log(o.a);
  console.log(o.b);
  o.c = 50;
  console.log(o.a);
})();

在 chrome 中调试视图如下:

图片描述

可以看到对象下多了 get 属性以及 set 属性
输出结果如下:

图片描述

当然 get 语句与 set 语句可以声明多次用来对应多个 gettersetter
使用这种方法的好处是可以在声明属性的时候同时声明对应的 gettersetter
这里就有人问了,能不能将o 对象的 get 及 set 方法的方法名都改成 “a”,这样就可以直接通过“.”来访问方法直接操作

(function () {
  var o = {
    a : 7,
    get a(){return this.a +1;},//死循环
    set a(x){this.a = x/2}
  };
  console.log(o.a);
  console.log(o.b);
  o.c = 50;
  console.log(o.a);
})();

打开 chrome 查看创建后的视图如下:

图片描述

可以看到这个时候的 get 与 set 方法已经和上面不同,但是是否真的能起作用呢,答案是否定的,当我们通过 o.a 调用的是 get语句 声明的 a方法,进入到该方法后遇到 this.a 方法继续调用该方法形成死循环最终导致死循环报内存溢出错误。

新语法(ES6):暂时只有 firefox 支持,其他浏览器会报错

(function () {
  var b = "bb";
  var c = "cc";
  var o = {
    a : 7,
    get [b](){return this.a +1;},
    set [c](x){this.a = x/2},
  };
  console.log(o.a);
  console.log(o[b]);
  o["cc"] = 50;
  console.log(o.a);
})();

打开 firefox 查看调试:

图片描述

输出结果如下:

图片描述

2.使用 Object.create 方法

引用 MDN:

概述Object.create() 方法创建一个拥有指定原型和若干个指定属性的对象。语法Object.create(proto, [ propertiesObject ])

我们都知道使用 Object.create 方法传递一个参数的时候可以创建一个以该参数为原型的对象 浅谈 JS 创建对象的 8 种模式
第二个参数是可选项,是一个匿名的参数对象,该参数对象是一组属性与值,该对象的属性名称将是新创建的对象的属性名称,值是属性描述符(包扩数据描述符或存取描述符,具体解释看后面的内容 什么是属性描述符)。
通过属性描述符我们可以实现为新创建的对象添加 get 方法以及 set 方法

(function () {
  var o = null;
  o = Object.create(Object.prototype,//指定原型为 Object.prototype
      {
        bar:{
          get :function(){
            return 10;
          },
          set : function (val) {
            console.log("Setting `o.bar` to ",val);
          }
        }
      }//第二个参数
    );
  console.log(o.bar);
  o.bar = 12;
})();

在 chrome 中调试试图如下:

图片描述

可以看到新创建对象通用多了 get 以及 set 属性
输出结果如下:

图片描述

上面这个例子并没有用来针对 get 方法以及 set 方法使用的属性

(function () {
  var o = null;
  o = Object.create(Object.prototype,//指定原型为 Object.prototype
      {
        bar:{
          get :function(){
            return this.a;
          },
          set : function (val) {
            console.log("Setting `o.bar` to ",val);
            this.a = val;
          },
          configurable :true
        }
      }//第二个参数
    );
  o.a = 10;
  console.log(o.bar);
  o.bar = 12;
  console.log(o.bar);
})();

亦或:

(function () {
  var o = {a:10};
  o = Object.create(o,//指定原型为 o 这里实际可以理解为继承
      {
        bar:{
          get :function(){
            return this.a;
          },
          set : function (val) {
            console.log("Setting `o.bar` to ",val);
            this.a = val;
          },
          configurable :true
        }
      }//第二个参数
    );
  console.log(o.bar);
  o.bar = 12;
  console.log(o.bar);
})();

输出结果如下:

图片描述

使用这种方式的好处是可配置性高,但初学者容易迷糊。

3.使用 Object.defineProperty 方法

引用 MDN:

概要
Object.defineProperty() 方法直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象。
语法
Object.defineProperty(obj, prop, descriptor)
参数
obj
需要定义属性的对象。
prop
需被定义或修改的属性名。
descriptor
需被定义或修改的属性的描述符。

(function () {
  var o = { a : 1}//声明一个对象,包含一个 a 属性,值为1
  Object.defineProperty(o,"b",{
    get: function () {
      return this.a;
    },
    set : function (val) {
      this.a = val;
    },
    configurable : true
  });

  console.log(o.b);
  o.b = 2;
  console.log(o.b);
})();

这个方法与前面两种的区别是:使用前面两种只能在声明定义的时候指定 getter 与 setter,使用该方法可以随时的添加或修改。

如果说需要一次性批量添加 getter 与 setter 也是没问题的,使用如下方法:

4.使用 Object.defineProperties方法

MDN:

概述
Object.defineProperties() 方法在一个对象上添加或修改一个或者多个自有属性,并返回该对象。
语法
Object.defineProperties(obj, props)
参数
obj
将要被添加属性或修改属性的对象
props
该对象的一个或多个键值对定义了将要为对象添加或修改的属性的具体配置

不难看出用法与 Object.defineProperty 方法类似

(function () {
  var obj = {a:1,b:"string"};
  Object.defineProperties(obj,{
    "A":{
      get:function(){return this.a+1;},
      set:function(val){this.a = val;}
    },
    "B":{
      get:function(){return this.b+2;},
      set:function(val){this.b = val}
    }
  });

  console.log(obj.A);
  console.log(obj.B);
  obj.A = 3;
  obj.B = "hello";
  console.log(obj.A);
  console.log(obj.B);
})();

输出结果如下:

图片描述

天意易趣网拍卖系统
天意易趣网拍卖系统

前台主要功能:首选服务 注销登陆 查看使用帮助 修改添加登陆帐号拍卖商品管理 管理拍卖商品 推荐拍卖商品 删除特定拍卖 已经结束商品 拍卖分类管理 新闻管理 添加文章 删除修改 栏目管理 新闻CSS设定 新闻JS生成 初始化新闻 参数设置 用户管理 未审核用户管理 普通用户管理 高级用户管理 黄金用户管理 管理所有用户 数据库管理 压缩数据库 备份数据库 恢复数据库 批量处理 系统指标测试V1.

下载

5.使用 Object.prototype.__defineGetter__ 以及 Object.prototype.__defineSetter__ 方法

(function () {
  var o = {a:1};
  o.__defineGetter__("giveMeA", function () {
    return this.a;
  });
  o.__defineSetter__("setMeNew", function (val) {
    this.a = val;
  })
  console.log(o.giveMeA);
  o.setMeNew = 2;
  console.log(o.giveMeA);
})();

输出结果为1和2
查看 MDN 有如下说明:

图片描述

什么是属性描述符

MDN:

对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。

  1. 数据描述符是一个拥有可写或不可写值的属性。

  2. 存取描述符是由一对 getter-setter 函数功能来描述的属性。

  3. 描述符必须是两种形式之一;不能同时是两者。

数据描述符和存取描述符均具有以下可选键值:

configurable
当且仅当这个属性描述符值为 true 时,该属性可能会改变,也可能会被从相应的对象删除。默认为 false。
enumerable
true 当且仅当该属性出现在相应的对象枚举属性中。默认为 false。

数据描述符同时具有以下可选键值:

value
与属性相关的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。
writable
true 当且仅当可能用 赋值运算符 改变与属性相关的值。默认为 false。

存取描述符同时具有以下可选键值:

get
一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。方法将返回用作属性的值。默认为 undefined。
set
一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将收到作为唯一参数的新值分配给属性。默认为 undefined。

以上是摘自MDN的解释,看起来是很晦涩的,具体什么意思呢:
首先我们从以上解释知道该匿名参数对象有个很好听的名字叫属性描述符,属性描述符又分成两大块:数据描述符以及存取描述符(其实只是一个外号,给指定的属性集合起个外号)。

数据描述符包括两个属性 : value 属性以及 writable 属性,第一个属性用来声明当前欲修饰的属性的值,第二个属性用来声明当前对象是否可写即是否可以修改

存取描述符就包括 get 与 set 属性用来声明欲修饰的象属性的 getter 及 setter

属性描述符内部,数据描述符与存取描述符只能存在其中之一,但是不论使用哪个描述符都可以同时设置 configurable 属性以及enumerable 属性。
configurable属性用来声明欲修饰的属性是否能够配置,仅有当其值为 true 时,被修饰的属性才有可能能够被删除,或者重新配置。
enumerable 属性用来声明欲修饰属性是否可以被枚举。

知道了什么是属性描述符,我们就可以开始着手创建一些对象并开始配置其属性

创建属性不可配置不可枚举的对象

//使用默认值配置
(function () {
  var obj = {};//声明一个空对象
  Object.defineProperty(obj,"key",{
    value:"static"
            //没有设置 enumerable 使用默认值 false
            //没有 configurable 使用默认值 false
            //没有 writable 使用默认值 false
  });

  console.log(obj.key);      //输出 “static”
  obj.key = "new"         //尝试修改其值,修改将失败,因为 writable 为 false
  console.log(obj.key);      //输出 “static”
  obj.a = 1;//动态添加一个属性
  for(var item in obj){ //遍历所有 obj 的可枚举属性
     console.log(item);
  }//只输出一个 “a” 因为 “key”的 enumerable为 false
})();
//显示配置 等价于上面
(function () {
  var obj = {};
  Object.defineProperty(obj,"key",{
    enumerable : false,
    configurable : false,
    writable : false,
    value : "static"
  })
})();
//等价配置
(function () {
  var o = {};
  o.a = 1;
  //等价于
  Object.defineProperty(o,"a",{value : 1,
                writable : true,
                configurable : true,
                enumerable : true});
  
  Object.defineProperty(o,"a",{value :1});
  //等价于
  Object.defineProperty(o,"a",{value : 1,
                writable : false,
                configurable : false,
                enumerable : false});
})();

Enumerable 特性
属性特性 enumerable 决定属性是否能被 for...in 循环或 Object.keys 方法遍历得到

(function () {
  var o = {};
  Object.defineProperty(o,"a",{value :1,enumerable :true});
  Object.defineProperty(o,"b",{value :2,enumerable :false});
  Object.defineProperty(o,"c",{value :2});//enumerable default to false
  o.d = 4;//如果直接赋值的方式创建对象的属性,则这个属性的 enumerable 为 true

  for(var item in o){ //遍历所有可枚举属性包括继承的属性
    console.log(item);
  }

  console.log(Object.keys(o));//获取 o 对象的所有可遍历属性不包括继承的属性

  console.log(o.propertyIsEnumerable('a'));//true
  console.log(o.propertyIsEnumerable('b'));//false
  console.log(o.propertyIsEnumerable('c'));//false
})();

输出结果如下:

图片描述

Configurable 特性

(function () {
  var o = {};
  Object.defineProperty(o,"a",{get: function () {return 1;},
                configurable : false} );
                //enumerable 默认为 false,
                //value 默认为 undefined,
                //writable 默认为 false,
                //set 默认为 undefined
                 
  //抛出异常,因为最开始定义了 configurable 为 false,故后期无法对其进行再配置
  Object.defineProperty(o,"a",{configurable : true} );
  //抛出异常,因为最开始定义了 configurable 为 false,故后期无法对其进行再配置,enumerable 的原值为 false
  Object.defineProperty(o,"a",{enumerable : true} );
  //抛出异常,因为最开始定义了 configurable 为 false,set的原值为 undefined
  Object.defineProperty(o,"a",{set : function(val){}} );
  //抛出异常,因为最开始定义了 configurable 为 false,故无法进行覆盖,尽管想用一样的来覆盖
  Object.defineProperty(o,"a",{get : function(){return 1}});
  //抛出异常,因为最开始定义了 configurable 为 false,故无法将其进行重新配置把属性描述符从存取描述符改为数据描述符
  Object.defineProperty(o,"a",{value : 12});

  console.log(o.a);//输出1
  delete o.a;   //想要删除属性,将失败
  console.log(o.a);//输出1
  
})();

提高及扩展
1.属性描述符中容易被误导的地方之 writable 与 configurable

(function () {
  var o = {};
  Object.defineProperties(o,{
    "a": {
      value:1,
      writable:true,//可写
      configurable:false//不可配置
      //enumerable 默认为 false 不可枚举
    },
    "b":{
      get :function(){
        return this.a;
      },
      configurable:false
    }
  });
  console.log(o.a);  //1
  o.a = 2;      //修改值成功,writable 为 true
  console.log(o.a);  //2
  Object.defineProperty(o,"a",{value:3});//同样为修改值成功
  console.log(o.a);  //3

  //将其属性 b 的属性描述符从存取描述符重新配置为数据描述符
  Object.defineProperty(o,"b",{value:3});//抛出异常,因为 configurable 为 false
})();

2.通过上面的学习,我们都知道传递属性描述符参数时,是定义一个匿名的对象,里面包含属性描述符内容,若每定义一次便要创建一个匿名对象传入,将会造成内存浪费。故优化如下:

(function () {
  var obj = {};

  //回收同一对象,即减少内存浪费
  function withValue(value){
    var d = withValue.d ||(
      withValue.d = {
        enumerable : false,
        configurable : false,
        writable : false,
        value :null
      }
      );
    d.value = value;
    return d;
  }
  Object.defineProperty(obj,"key",withValue("static"))
})();

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

FileReader API的使用

vue内置指令方法与事件

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
拼多多赚钱的5种方法 拼多多赚钱的5种方法
拼多多赚钱的5种方法 拼多多赚钱的5种方法

在拼多多上赚钱主要可以通过无货源模式一件代发、精细化运营特色店铺、参与官方高流量活动、利用拼团机制社交裂变,以及成为多多进宝推广员这5种方法实现。核心策略在于通过低成本、高效率的供应链管理与营销,利用平台社交电商红利实现盈利。

28

2026.01.26

edge浏览器怎样设置主页 edge浏览器自定义设置教程
edge浏览器怎样设置主页 edge浏览器自定义设置教程

在Edge浏览器中设置主页,请依次点击右上角“...”图标 > 设置 > 开始、主页和新建标签页。在“Microsoft Edge 启动时”选择“打开以下页面”,点击“添加新页面”并输入网址。若要使用主页按钮,需在“外观”设置中开启“显示主页按钮”并设定网址。

8

2026.01.26

苹果官方查询网站 苹果手机正品激活查询入口
苹果官方查询网站 苹果手机正品激活查询入口

苹果官方查询网站主要通过 checkcoverage.apple.com/cn/zh/ 进行,可用于查询序列号(SN)对应的保修状态、激活日期及技术支持服务。此外,查找丢失设备请使用 iCloud.com/find,购买信息与物流可访问 Apple (中国大陆) 订单状态页面。

31

2026.01.26

npd人格什么意思 npd人格有什么特征
npd人格什么意思 npd人格有什么特征

NPD(Narcissistic Personality Disorder)即自恋型人格障碍,是一种心理健康问题,特点是极度夸大自我重要性、需要过度赞美与关注,同时极度缺乏共情能力,背后常掩藏着低自尊和不安全感,影响人际关系、工作和生活,通常在青少年时期开始显现,需由专业人士诊断。

3

2026.01.26

windows安全中心怎么关闭 windows安全中心怎么执行操作
windows安全中心怎么关闭 windows安全中心怎么执行操作

关闭Windows安全中心(Windows Defender)可通过系统设置暂时关闭,或使用组策略/注册表永久关闭。最简单的方法是:进入设置 > 隐私和安全性 > Windows安全中心 > 病毒和威胁防护 > 管理设置,将实时保护等选项关闭。

5

2026.01.26

2026年春运抢票攻略大全 春运抢票攻略教你三招手【技巧】
2026年春运抢票攻略大全 春运抢票攻略教你三招手【技巧】

铁路12306提供起售时间查询、起售提醒、购票预填、候补购票及误购限时免费退票五项服务,并强调官方渠道唯一性与信息安全。

35

2026.01.26

个人所得税税率表2026 个人所得税率最新税率表
个人所得税税率表2026 个人所得税率最新税率表

以工资薪金所得为例,应纳税额 = 应纳税所得额 × 税率 - 速算扣除数。应纳税所得额 = 月度收入 - 5000 元 - 专项扣除 - 专项附加扣除 - 依法确定的其他扣除。假设某员工月工资 10000 元,专项扣除 1000 元,专项附加扣除 2000 元,当月应纳税所得额为 10000 - 5000 - 1000 - 2000 = 2000 元,对应税率为 3%,速算扣除数为 0,则当月应纳税额为 2000×3% = 60 元。

12

2026.01.26

oppo云服务官网登录入口 oppo云服务登录手机版
oppo云服务官网登录入口 oppo云服务登录手机版

oppo云服务https://cloud.oppo.com/可以在云端安全存储您的照片、视频、联系人、便签等重要数据。当您的手机数据意外丢失或者需要更换手机时,可以随时将这些存储在云端的数据快速恢复到手机中。

40

2026.01.26

抖币充值官方网站 抖币性价比充值链接地址
抖币充值官方网站 抖币性价比充值链接地址

网页端充值步骤:打开浏览器,输入https://www.douyin.com,登录账号;点击右上角头像,选择“钱包”;进入“充值中心”,操作和APP端一致。注意:切勿通过第三方链接、二维码充值,谨防受骗

7

2026.01.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8.5万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号