JS添加getter+setter总结

这次给大家带来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 语句可以声明多次用来对应多个 getter 和 setter
使用这种方法的好处是可以在声明属性的时候同时声明对应的 getter 和 setter
这里就有人问了,能不能将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);})();

登录后复制

输出结果如下:

图片描述

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:

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

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

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

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

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

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"))})();

登录后复制

相信看了本文案例你已经掌握了方法,更多精彩请关注【创想鸟】其它相关文章!

推荐阅读:

FileReader API的使用

FileReader API的使用

以上就是JS添加getter+setter总结的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/3185392.html

(0)
上一篇 2025年3月31日 22:23:29
下一篇 2025年3月31日 22:23:43

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 使用js实现微信唤起支付宝领红包(详细教程)

    最近支付宝的领红包可真是刷爆了各个微信群啊,满群都是支付宝口令,可是这样推广很麻烦,下面我给大家带来了js实现微信/qq直接跳转到支付宝app打开口令领红包功能,需要的朋友参考下 最近支付宝的领红包可真是刷爆了各个微信群啊,满群都是支付宝口…

    2025年5月1日 编程技术
    000
  • JS实现简易版贪吃蛇小游戏

    nbsp;html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>    新建网页     …

    编程技术 2025年4月4日
    200
  • phpstorm怎么用js

    一、PHPStorm调试Javascript 在PHPStorm中创建test.html nbsp;html>        Test page     var test; var test2; console.log(“hello …

    2025年4月2日 编程技术
    200
  • vscode怎么压缩js代码

    vscode压缩js代码的方法: 1、在拓展商店里搜索“minify”,安装,安装成功后点重新加载 2、使用:F1运行文件缩小器Minify压缩js代码。 使用Minify的方法介绍: 缩小您的js,css和html文件以节省传输带宽。直接…

    2025年4月2日
    200
  • 怎么在vscode中调试js代码

    在左侧扩展中搜索debugger for chrome并点击安装 在自己的html工程目录下面点击f5,或者在左侧选择调试按钮 选择下拉按钮,会有一个添加,选择chrome 之后会出现laungh.json的配置文件在自己的项目目录下面 不…

    2025年4月2日 编程技术
    200
  • vscode如何配置js运行环境

    vscode界面很简洁安装完之后所有的功能都一目了然,我们需要安装插件可以点击如图的工具和语言: 安装以下两个插件如图:(你也可以选择其他这里只是示例) 我们要调试一个js,需要创建一个html文档里面添加js方法,简单创建个文件,可以直接…

    2025年4月2日 编程技术
    100
  • vue.js核心最基本的功能是什么

    vue.js核心最基本的功能是一个允许采用简洁的模板语法来声明式地将数据渲染进DOM的系统。vue.js的核心功能使得我们可以很方便地控制切换一个元素是否显示。 本文操作环境:windows10系统、vue 2.5.2、thinkpad t…

    2025年4月1日
    400
  • 深入了解Vuex中的State和Getter

    vuex 的内脏由五部分组成:state、getter、mutation、action 和 module。本篇文章先带大家深入了解一下vuex中的state和getter,希望对大家有所帮助! Vuex_State Vuex是vue的状态管…

    2025年4月1日
    100
  • 怎么用JavaScript在Vue3中实现动画?

    概述 动画的实现其实不仅可以使用css的方式实现,而且还可以使用js的方式实现,二者有啥区别呢?css更加注重动画的展现,性能更好,而js的方式性能稍微差点,但是可以在动画执行的每一个过程中做些额外的操作。也就是说动画执行的开始-执行中-结…

    编程技术 2025年4月1日
    200
  • 利用JS实现点击按钮后图片自动切换的简单方法

    我么常常看到一个网站的主界面的图片可以切换自如,那么又是如何实现的呢? 1.HTML页面布局如图所示: 2.实现上述布局 swap.html    nbsp;html PUBLIC ‘-//W3C//DTD HTML 4.01 Strict…

    2025年4月1日
    200

发表回复

登录后才能评论