《JS高级程序设计-第3版》的读书笔记关于对象
ECMAScript与其他OO语言对象的区别:js中没有类的概念,但是有对象的概念,ECMA-262把对象定义为,无序属性的集合,其属性可以包含基本值、对象或者函数。这里我将其当成java中的HashMap<Key, Object>,一个HashMap对应一个对象。应为没有类的概念所以对象的创建也有一些不同。在js里每个对象都是基于一个引用类型创建的(或者说是'对象定义')。可以是js原生类型(例如:Object、Array、Date)也可以是自定义的引用类型。
对象的创建:对象的创建的统一方式是new操作符后跟构造函数。例如:var person = new Object()。但是对于不同的类型还可能存在着不同的字面量表示法。例如Object和Array类型:
Object类型,使用字面量表示法创建对象 var person = { "name" : "abc", //属性名也可以是字符串 age : 18, 5 : true //最后一个属性后没有逗号,不同版本浏览器可能会出错,数值5转化为字符串 }; //这有个分号,js中表达式上下文指的是能够返回一个值(表达式),这里的{}及其内部构成表达式 var person ={}; //与new Object()相同,现在版本这句话不会调用Object构造函数,以前的可能。 person.name = "abc"; person.age = 18; Array类型,使用字面量表示法创建对象 var colors = ["red", "blue", "green"]; //创建一个包含3个字符串的数组 var names = []; //创建一个空数组 var values = [1,2,]; // 不要这样!这样会创建一个包含2或者3项的数组 var options = [,,,,,]; // 不要这样!这样会创建一个包含5或者6项的数组
在js中可以用person.name来访问属性,也可以用person["name"]这种方括号语法,方括号语法可以访问一些特别的属性名,类如person["first name"],或者访问属性名是关键字或保留字的属性。
对象的属性:js中有两种属性,数据属性和访问器属性。不同的属性有不同的特性,这些特性描述了属性的各种特征。(类比为,属性为成员变量,特性为public、static、final这些修饰符),特性是给js引擎用的,不能直接访问。
数据属性:数据属性包含一个数据值的位置,在这个位置可以读写。即可以通过person.name这样访问和赋值的属性。该属性有四个特性:
[[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把苏醒修改为访问器属性 。对于直接在对象上定义的属性,如上例该值默认为true。
[[Enumerable]]:表示能否通过for-in循环返回属性。对于直接在对象上定义的属性,如上例该值默认为true。
[[Writable]]:表示能够修改属性的值。对于直接在对象上定义的属性,如上例该值默认为true。
[[Value]]:包含这个属性的数据值。读写都是在这个位置。默认为undefined。
属性的特性可以修改,但是要使用ECMAScript5的Object.defineProperty()方法。这个方法就收三个参数:属性所在对象、属性的名字和一个描述符对象。其中描述符对象必须为上面的特性的一个或多个(注意首字母小写,js是区别大小写的)。
var person = {}; Object.defineProperty(person, "name", { writable: false, //即便删除这一行,下面输出部分的结果也是一样的。 value: "Nicholas" }); alert(person.name); //"Nicholas" person.name = "Greg"; alert(person.name); //"Nicholas"
在非严格模式会忽略,在严格模式会报错。这里值得注意的地方有两个。其一、如果这里修改的特性如果为configurable,即将configurable修改为false,那么你就没有办法修改回来了。其二、这里了传入的特性虽然只有一个,但是默认为传入四个值,并且默认值都是false(value默认为undefined)。这也就意味着一旦defineProperty运行,只有传入的特性可以操控,其余的都是false。即上面的方法调用后,其实即便删除writable: false。其结果也是一样的。
访问器属性:访问器属性不包含数据值。它们包含一堆getter和setter函数(不过,这两个函数都不是必需的)。这两句话我的理解是,这个属性因为它包含两个函数,为了方便使用这两函数,用一个标识符来代替这两个函数,以达到用"对象名.访问器属性"这种方式就能访问这两个函数的程度。这个标识符就是访问器属性。该属性有四个特性如下。
[[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为数据属性。对于直接在对象上定义的属性,(访问器也可以直接定义?)默认为true。
[[Enumerable]]:表示能否通过for-in循环返回属性。对于直接在对象上定义的属性,(访问器也可以直接定义?)默认为true。
[[Get]]:在读取属性时调用的函数。默认为undefined。
[[Set]]:在写入属性时调用的函数。默认为undefined。
访问器属性不能直接定义,必须用Object.defineProperty()来定义,例子如下:
var book = { _year: 2004, //_year前面的下划线是一种常用的记号,用于表达只能通过对象方法访问的属性。 edition: 1 //当然这是一种约定,你要是非要用点访问法访问,也是可以访问的 }; Object.defineProperty(book, "year", { get: function(){ return this._year; }, set: function(newValue){ if (newValue > 2004) { this._year = newValue; this.edition += newValue - 2004; } } }); book.year = 2005; alert(book.edition); //2
上面例子就是访问器属性的常见用法,即设置一个属性的值导致其他属性发生变化。其在调用defineProperty()方法后同样存在不操作的属性设置为false。(get和set属性设置为undefined的情况,get和set还不知道怎么验证所以括起来,有可能get和set为指向getter和setter的指针,也有可能为null)。但是只对访问器属性有效果,例如上例,enumerable和configurable变成了false,但是只对year这个属性起作用,在for-in中不返回year属性,delete book.year; 无效果。
两个遗留的方法创建访问器属性:
var book = { _year: 2004, edition: 1 }; book.__defineGetter__("year", function(){ //遗留的__defineGetter__()方法 return this._year; }); book.__defineSetter__("year", function(newValue){ //一流的__defineSetter__()方法 if (newValue > 2004) { this._year = newValue; this.edition += newValue - 2004; } }); book.year = 2005; alert(book.edition); //2
ECMAScript 5 中有个Object.defineProperties()的方法,用于复制属性和属性的特性。第一个参数时要添加和修改的对象,第二个是模板,第二个对象的属性和第一个对象的某个属性相同时应该就是修改了。
var book = { x:100 }; var fee = { _year: { //由下面for-in的输出结果可以看出,这种属性后加{}来定义属性的方式 value: 2004 //会使其余特性会变成false,因为不是在对象上直接定义 }, edition: { value: 1 }, say: { value: function(){ alert("123"); } }, year: { get: function(){ return this._year; }, set: function(newValue){ if (newValue > 2004) { this._year = newValue; this.edition += newValue - 2004; } } } } Object.defineProperties(book, fee); //fee可以用fee等号右边的整个来代替 for(var y in book){ console.log(y); //只输出了属性x,因为其余属性的enumerable都为false } book.say(); console.log(book.year); console.log(book.x); //原本的book.x并没有发生改变
ECMAScript 5 中的Object.getOwnPropertyDescriptor()用于读取属性的特性,属性不同对应不同的特性,第一个参数为对象,第二个参数为属性名称。返回一个以特性为属性的对象,属性值为原本的特性值。如下
var book = {}; Object.defineProperties(book, { _year: { value: 2004 }, edition: { value: 1 }, year: { get: function(){ return this._year; }, set: function(newValue){ if (newValue > 2004) { this._year = newValue; this.edition += newValue - 2004; } } } }); var descriptor = Object.getOwnPropertyDescriptor(book, "_year"); alert(descriptor.value); //2004 alert(descriptor.configurable); //false alert(typeof descriptor.get); //"undefined" var descriptor = Object.getOwnPropertyDescriptor(book, "year"); alert(descriptor.value); //undefined alert(descriptor.enumerable); //false alert(typeof descriptor.get); //"function"
转载于:https://www.cnblogs.com/ant-xu/p/11255498.html
- JS高级程序设计--读书笔记(BOM对象)
- 读书笔记 - js高级程序设计 - 第六章 面向对象的程序设计
- JavaScript高级程序设计(第3版)学习笔记6 初识js对象
- JavaScript高级程序设计(第3版)学习笔记11 内建js对象
- JavaScript高级程序设计(第3版)学习笔记11 内建js对象
- JavaScript高级程序设计(第3版)学习笔记6 初识js对象
- JS高级程序设计--读书笔记(js对象创建)
- js高级程序设计读书笔记
- JS高级程序设计第3章读书笔记
- 读书笔记 - js高级程序设计 - 第五章 引用类型
- JavaScript高级程序设计(第3版)第八章读书笔记
- 读书笔记 - js高级程序设计 - 第十章 DOM
- JavaScript高级程序设计(第3版)学习笔记5 js语句
- JavaScript高级程序设计 读书笔记之十 本地对象Date日期
- 读书笔记 - js高级程序设计 - 第三章 基本概念
- JavaScript高级程序设计(第3版)读书笔记汇总
- JavaScript高级程序设计 读书笔记之九 本地对象Array
- JavaScript高级程序设计(第3版)第七章读书笔记
- C#2008与.NET 3.5 高级程序设计读书笔记(8)--对象的生命周期
- JavaScript高级程序设计 读书笔记之十一 内置对象Global