文档章节

js对象中的属性类型

hirainn
 hirainn
发布于 2016/05/26 12:45
字数 1041
阅读 28
收藏 0

ECMA-262在第五版定义只有内部才有的特性时,描述了属性的各种特征,这些特性时为了实现javascript引擎用的,因此在javascript中不能直接访问他们.

ECMAScript中有两种属性,数据属性跟访问器属性.

1.数据属性

数据属性包含一个数据值的位置.在这个位置可以读取和写入值,数据属性有4个描述其行为的特性.

  • [[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,即更改该属性的其他特性,或者能否把属性修改为访问器属性,默认值为true.值得一说的是,一旦将该属性设置成false之后,就无法重新设置成true.
  • [[Enumerable]]:表示能否通过for-in循环返回属性,默认为true.
  • [[Writable]]:表示能否修改属性的值,默认为true
  • [[Value]]:属性的值,读取属性值的时候,从这个属性读,写入属性值的时候,把新值保存在这个位置,默认值为undefined.
var person = {
    name : "Rainn",
    age : 25,
    job : "IT"
};
Object.defineProperty(person,"name",{
    writable : false,
});
Object.defineProperty(person,"age",{
    writable : false,
    enumerable : false,
});
Object.defineProperty(person,"job",{
    configurable : false
})
person.name = "test";
person.age = 18;
person.job = "Singer";
alert(person.name);   //Rainn
alert(person.age);    //25
alert(person.job);    //Singer
for(var p in person){
	console.log(person[p])
}
//Rainn
//Singer

name跟age 都设置了不可写,所以返回结果还是之前定义的值,age设置了不可循环出来,所以最终循环出来的结果,把age跳过去了.

因为name并没有设置不可配置,所以这个时候可以更改name的数据属性,达到重新写入的目的,而因为job设置了不可配置,所以,再操作任何job的数据属性,都会抛出一个错误

Object.defineProperty(person,"name",{
    writable : true
});
person.name = "test";
alert(person.name); //test
Object.defineProperty(person,"job",{
    configurable : true
}); //Uncaught TypeError: Cannot redefine property: job

上述写法,太麻烦?是的.设置单一属性的时候用defineProperty,而设置多属性的时候,可以直接用defineProperties,也建议这么写,这样代码维护的时候也比较方便,以上代码可以写作

Object.defineProperties(person,{
    name : {
        writable : false,
        configurable : false
    },
    age : {
        writable : false,
        enumerable : false
    },
    job : {
        configurable : false
    }
})

2.访问器属性

访问器属性不包含数据值,包含一对getter和setter函数,两个函数都不是必要的,默认值均为undefined,在读取访问器属性时,会先调用getter函数,在写入访问器属性时,会先调用setter函数,并传入新值,类似某些语言的魔术方法__GET跟__SET,只是这里只控制单一属性.同样的,访问器属性,也有4个特性,其中Configurable跟Enumerable跟数据特性一样,这里不再细说.

先看一段错误代码:

var person = {
    name : "Rainn",
    age : 25
}
Object.defineProperties(person,{
    name : {
        get : function(){
            return "hello! I'm " + this.name; 
        },
        set function(newValue){
            this.name = newValue + "(changed)";
        }
    },
    age : {
        get : function(){
            return "18 forever";
        },
        set : function(){
            this.age -= 1;
        }
    }
});

如果代码这么写的话,会报出堆栈溢出,原因在于,读name的时候,会访问get,get中继续读了this.name,就会无限读,造成堆栈溢出,所以,一般用一个替代的属性处理,习惯性的用_+属性名表示.,用于表示只能通过对象方法访问的属性

var person = {};
Object.defineProperties(person,{
	_name : {
		value : "Rainn",
		writable : true,
	},
	_age : {
		value : 25,
		writable : true,
	},
	name : {
		get : function(){
			return this._name;
		},
		set : function(newValue){
			this._name = newValue + '(used)';
		}
	},
	age : {
		get : function(){
			return '18 forever';
		},
		set : function(){
			this._age -= 1;
		}
	}
});
alert(person.name);   //Rainn
person.name = "Tom";  
alert(person.name);   //Tom(used)
alert(person.age);    //18 forever
person.age = 18;
person.age = 18;
alert(person._age);   //23

这里还有一点需要提出来 ,在申明对象是,如果在自变量中声明了属性,则这个属性的数据特性都是默认true,即使更改其中某一项,其他的还是true,而如果在声明对象的时候,自变量中没有定义的属性,则均默认为false;

查看属性特性的方法为Object.getOwnPropertyDescriptor()

var person = {
	name : "rainn"
};
Object.defineProperties(person, {
	name : {
		writable : false
	},
	_age : {
		value : 25
	}
})
var nameDes = Object.getOwnPropertyDescriptor(person,'name');
var ageDes = Object.getOwnPropertyDescriptor(person,'_age'); 
console.log(nameDes); //{value: "rainn", writable: false, enumerable: true, configurable: true}
console.log(ageDes);  //{value: 25, writable: false, enumerable: false, configurable: false}

 

© 著作权归作者所有

hirainn
粉丝 35
博文 84
码字总数 65318
作品 0
深圳
程序员
私信 提问
细说JavaScript数据类型及转换

细说JavaScript数据类型及转换 JavaScript数据类型 1.Boolean(布尔) 布尔:(值类型)var b1=true;//布尔类型 2.Number(数字) 数值:(值类型)var n1=3.1415926;//数值类型 n1.toFixed...

开元中国2015
2015/07/13
103
1
JavaScript基础学习总结

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 https://blog.csdn.net/fengxinlinux/article/details/96162470 文章目录 document.getElem...

Rotation.
07/16
0
0
使用 SpiderMonkey 脚本化您的应用

SpiderMonkey 简介 和其他的 JavaScript 引擎一样,SpiderMonkey 不直接提供像 DOM 这样的对象,而是提供解析,执行 JavaSccript 代码,垃圾回收等机制。SpidlerMonkey 是一个在 Mozilla 之下...

红薯
2011/02/18
3.2K
3
JavaScript 数据类型

字符串、数字、布尔、数组、对象、Null、Undefined JavaScript 拥有动态类型 JavaScript 拥有动态类型。这意味着相同的变量可用作不同的类型: 实例 var x // x 为 undefinedvar x = 6; // x...

丿Dean
2014/09/12
42
0
《JavaScript面向对象精要》之一:基本类型和引用类型

1.1 什么是类型 原始类型 保存为简单数据值。 引用类型 保存为对象,其本质是指向内存位置的引用。 为了让开发者能够把原始类型和引用类型按相同的方式处理,JavaScript 花费了很大的努力来保...

明易
2018/12/17
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring使用ThreadPoolTaskExecutor自定义线程池及实现异步调用

多线程一直是工作或面试过程中的高频知识点,今天给大家分享一下使用 ThreadPoolTaskExecutor 来自定义线程池和实现异步调用多线程。 一、ThreadPoolTaskExecutor 本文采用 Executors 的工厂...

CREATE_17
今天
5
0
CSS盒子模型

CSS盒子模型 组成: content --> padding --> border --> margin 像现实生活中的快递: 物品 --> 填充物 --> 包装盒 --> 盒子与盒子之间的间距 content :width、height组成的 内容区域 padd......

studywin
今天
7
0
修复Win10下开始菜单、设置等系统软件无法打开的问题

因为各种各样的原因导致系统文件丢失、损坏、被修改,而造成win10的开始菜单、设置等系统软件无法打开的情况,可以尝试如下方法解决 此方法只在部分情况下有效,但值得一试 用Windows键+R打开...

locbytes
昨天
8
0
jquery 添加和删除节点

本文转载于:专业的前端网站➺jquery 添加和删除节点 // 增加一个三和一节点function addPanel() { // var newPanel = $('.my-panel').clone(true) var newPanel = $(".triple-panel-con......

前端老手
昨天
8
0
一、Django基础

一、web框架分类和wsgiref模块使用介绍 web框架的本质 socket服务端 与 浏览器的通信 socket服务端功能划分: 负责与浏览器收发消息(socket通信) --> wsgiref/uWsgi/gunicorn... 根据用户访问...

ZeroBit
昨天
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部