向JS对象添加getter和setter的五种方法
定义获取器和设置器
1.通过对象初始值设定项创建对象时指示(通过文字值创建对象时也可以称为声明)
(function () { var o={ a : 7,get b(){ return this . a 1;},//通过get和set的b和c方法间接修改a属性集c(x){ this . a=x/2 };console . log(o . a);console . log(o . b);o.c=50console . log(o . a);})();在chrome中调试视图,如下所示:
可以看到对象下有更多的get属性,设置属性的输出结果如下:
当然,get语句和set语句可以声明多次,以对应多个getters和setters。这种方法的优点是在声明属性时可以同时声明相应的getters和setters。这里有人问,能不能把O对象的get和set方法的方法名改成“A”,这样就可以直接通过“.”访问方法了
(function () { var o={ a : 7,get a(){ return this . a 1;},//无限循环集a(x){ this . a=x/2 } };console . log(o . a);console . log(o . b);o.c=50console . log(o . a);})();打开chrome查看创建的视图,如下所示:
我们可以看到此时的get和set方法与上面的不同,但是不管它们是否真的工作,答案都是否定的,当我们通过o.a调用get语句声明的A方法时,在进入这个方法后,我们遇到了this.a方法继续调用这个方法形成一个无限循环,最终导致一个无限循环报告内存溢出错误。
新语法(ES6):目前只有火狐支持,其他浏览器会报错
(function(){ var b=' bb ';var c=' ccvar o={ a : 7,get[b](){ return this . a 1;},设置[c](x){this.a=x/2},};console . log(o . a);console . log(o[b]);o[' cc ']=50;console . log(o . a);})();打开firefox查看调试:
输出结果如下:
2.使用对象创建方法
参考MDN:
方法创建一个具有指定原型和几个指定属性的对象。
语法对象。创建(原型,[属性对象])
众所周知,当使用Object.create方法传递参数时,我们可以基于这个参数创建一个对象。第二个参数是可选的,它是一个匿名参数对象。参数对象是一组属性和值。这个对象的属性名将是新创建对象的属性名,值将是属性描述符(包括数据描述符或访问描述符,具体在下面的内容中解释什么是属性描述符)。通过属性描述符,我们可以向新创建的对象添加get方法和set方法
(函数(){ var o=nullo=object . create(object . prototype,//将原型指定为object . prototype { bar : { get 3360 function(){ return 10;},设置:函数(val) { console.log('设置` o.bar `为',val);} } }//第二个参数);console . log(o . bar);o.bar=12})();chrome中的调试尝试如下:
可以看到新创建的对象比较常见,get和set属性的输出结果如下:
的get方法和set方法使用的属性不使用上述示例
(函数(){ var o=nullo=object . create(object . prototype,//将原型指定为object . prototype { bar : { get 3360 function(){ return this . a;},设置:函数(val) { console.log('设置` o.bar `为',val);this.a=val},可配置:true} }//第二个参数);o.a=10console . log(o . bar);o.bar=12console . log(o . bar);})();或者:
(function(){ var o={ a :10 };O=Object.create(o,//将prototype指定为o实际上可以理解为继承{ bar : { get 3360 function(){ return this . a;},设置:函数(val) { console.log('设置` o.bar `为',val);this.a=val},可配置:true} }//第二个参数);console . log(o . bar);o.bar=12console . log(o . bar);})();输出结果如下:
使用这种方法的优点是可配置性高,但是初学者很容易混淆。
3.使用对象定义属性方法
参考MDN:
summary Object.defineProperty()方法直接在对象上定义新属性,或者修改现有属性并返回该对象。语法对象。定义属性(对象、道具、描述符)参数对象需要定义属性的对象。属性要定义或修改的属性的名称。描述符要定义或修改的属性的描述符。
(function () {var o={a : 1}//声明一个对象,该对象包含一个a属性,值为1object。defineproperty (o,' b ',{ get: function(){ return this . a;},设置:函数(val){ this . a=val;},可配置: true });console . log(o . b);o . b=2;console . log(o . b);})();此方法与前两种方法的区别在于,使用前两种方法在声明定义时只能指定getter和setter,并且可以随时添加或修改此方法。
如果需要一次分批添加getter和setter,也没问题。使用以下方法:
4.使用对象定义属性方法
多边开发银行:
方法在一个对象上添加或修改一个或多个自己的属性,并返回该对象。语法对象。定义属性(对象,道具)参数对象要添加或修改的对象道具该对象的一个或多个键值对定义要为该对象添加或修改的属性的特定配置
不难看出,它的用法类似于Object.defineProperty方法
(function () { var obj={a:1,b : ' string ' };object . defineperoperties(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);物体。a=3;物体。B='你好';console.log(obj。a);console.log(obj。b);})();输出结果如下:
使用对象。原型。_ _ definegetter _ _和object。原型。_ _ definesetter _ _方法
(function(){ var o={ a :1 };o.__defineGetter__('giveMeA ',function(){ return this . a;});o.__defineSetter__('setMeNew ',function(val){ this . a=val;})console . log(o . give mea);o . setmenew=2;console . log(o . GiveMeA);})();输出结果是1和2。有关以下说明,请参见MDN:
什么是属性描述符
多边开发银行:
对象中有两种主要类型的属性描述符:数据描述符和访问描述符。
数据描述符是具有可写或未写值的属性。
访问描述符是由一对getter-setter函数描述的属性。
描述符必须是两种形式之一;不可能两者同时出现。
数据描述符和访问描述符都有以下可选键值:
可配置如果且仅当属性描述符值为真时,属性可能会更改或从相应的对象中删除。默认值为false。当且仅当属性出现在相应的对象枚举属性中时,可枚举true。默认值为false。
数据描述符还有以下可选键值:
与属性关联的值。它可以是任何有效的JavaScript值(数值、对象、函数等)。).默认值未定义。当且仅当可以使用赋值运算符更改与属性关联的值时,可写true。默认值为false。
访问描述符还有以下可选键值:
Get是一种为属性提供getter的方法,如果没有getter,则是未定义的。方法返回用作属性的值。默认值未定义。Set是为属性提供设置器的方法,如果没有设置器,则是未定义的。方法将作为唯一参数接收的新值分配给属性。默认值未定义。
以上解释摘自MDN,看起来很晦涩。具体是什么意思?首先,从上面的解释我们知道匿名参数对象有一个好听的名字叫做属性描述符,它分为两个块:数据描述符和访问描述符(其实只是一个昵称,给指定的属性集起了一个昵称)。
数据描述符包括两个属性:值属性和可写属性。第一个属性用于声明要修改的属性值,第二个属性用于声明当前对象是否可写,即是否可以修改。
访问描述符包括getter和setter,由get和set属性用来声明要修改的图像属性
在属性描述符中,数据描述符和访问描述符只能存在一个,但无论使用哪个描述符,都可以同时设置可配置属性和可枚举属性。可配置属性用于声明要修饰的属性是否可以配置。只有当其值为真时,才能删除或重新配置修饰属性。可枚举属性用于声明要修饰的属性是否可以枚举。
知道了什么是属性描述符,我们就可以开始创建一些对象,并开始配置它们的属性
创建一个属性不可配置且无法枚举的对象
//使用默认值配置(function(){ var obj={ };//声明一个空的对象对象。defineproperty (obj,' key ',{ value : ' static '//enumerable未设置为使用默认值false //可配置为使用默认值false //可写为使用默认值false });console . log(obj . key);//输出“static”obj . key=' new '///尝试修改其值,修改会失败,因为可写为false console . log(obj . key);//输出“static”obj . a=1;//为(obj中的var item)动态添加属性{//遍历所有obj的可枚举属性console . log(item);}//只输出一个“a”,因为“key”的可枚举为false })();//显示配置相当于上面的(function(){ var obj={ };object . defineperoperty(obj,' key ',{可枚举: false,可配置: false,可写: false,值: ' static ' })}));//等效配置(function(){ var o={ };o . a=1;//相当于对象。defineproperty (o,' a ',{value: 1,writeable: true,可配置: true,可枚举3360 true });object . definepreproperty(o,' a ',{ value :1 });//相当于对象。defineproperty (o,' a ',{value: 1,writeable: false,可配置: false,可枚举3360 false });})();可枚举属性属性属性可枚举确定属性是否可以由.循环或对象键方法
(function(){ var o={ };object . definepreproperty(o,' a ',{value :1,可枚举: true });object . definepreproperty(o,' b ',{value :2,可枚举: false });object . definepreproperty(o,' c ',{ value :2 });//可枚举默认值为false o . d=4;//如果对象的属性是通过直接赋值创建的,则该属性的可枚举值对于(o中的var item){//遍历所有可枚举属性,包括继承的属性console . log(item);} console . log(object . key(o));//获取o对象的所有遍历属性,不包括继承的属性console . log(o . properties enumerable(' a '));//true console . log(o . properties isenumerable(' b '));//false console . log(o . properties isenumerable(' c '));//false })();输出结果如下:
可配置属性
(function(){ var o={ };object . defineperoperty(o,' a ',{ get : function(){ return 1;},可配置: false });//可枚举默认为false,//值默认为undefined,//可写默认为false,//设置默认值为undefined //抛出异常,因为可配置刚开始定义为false,所以以后无法重新配置。Object.defineproperty (o,' a ',{可配置3360 true });//抛出异常,因为可配置在开始时定义为false,以后不能重新配置,可枚举的原始值为false object。defineproperty (o,' a ',{ enumerable : true });//抛出异常,因为可配置定义为false,设置开头,set的初始值为undefined object。defineproperty (o,' a ',{ set : function(val){ } });//引发异常,因为可配置在开始时被定义为false,所以无法覆盖,尽管您想用同一个对象覆盖object.defineproperty (o,' a ',{ get: function(){ return 1 } });//抛出异常,因为可配置在开头定义为false,所以无法重新配置,属性描述符从访问描述符改为数据描述符对象。defineproperty (o,' a ',{ value :12 });console . log(o . a);//输出1删除o.a//如果要删除属性,会失败console . log(o . a);//输出1 })();改进和扩展1。属性描述符中误导性位置的可写和可配置
(function(){ var o={ };object . definepreproperties(o,{'a' : {value:1,可写3360 true,//可写可配置:false//不可配置//可枚举默认为false且无法枚举},' b ' : { get3360 function(){ return this.},configurable : false } });console . log(o . a);//1 o . a=2;//值修改成功,可写为true console . log(o . a);//2 object . definepreproperty(o,' a ',{ value :3 });//同样是修改值成功的console . log(o . a);//3 //将其属性B的属性描述符从访问描述符重新配置为数据描述符Object。定义属性(o,' b ',{ value :3 });//引发异常,因为可配置为false })();2.通过以上研究,我们都知道在传递属性描述符参数时,定义了一个匿名对象,其中包含了属性描述符内容。如果创建一个匿名对象来传递每个定义,这将导致内存浪费。因此,优化如下:
(function(){ var obj={ };//回收同一个对象,也就是用value (value)减少内存浪费函数{ var d=with value . d | |(with value . d={可枚举: false,可配置3360 false,可写3360 false,value 3360 null });d.value=值;返回d;} object . defineperoperty(obj,' key ',with value(' static ')}))();本文到此结束。你可以看到更多发表在我们面前的文章。
版权声明:向JS对象添加getter和setter的五种方法是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。