JavaScript高级程序设计学习(五)之对象

简介: 众说周知,java是面向对象的编程语言。一个类包含多个对象,例如车类,它包含宝马,奔驰,东风,本田,莲花等这样的车,而品牌和颜色或者某种标识就是它的属性。车包含很多种类,但是共性还是有的,比如共性有四个轮子,有品牌,有发动机等等。

众说周知,java是面向对象的编程语言。一个类包含多个对象,例如车类,它包含宝马,奔驰,东风,本田,莲花等这样的车,而品牌和颜色或者某种标识就是它的属性。车包含很多种类,但是共性还是有的,比如共性有四个轮子,有品牌,有发动机等等。这些可以抽象为一个类,让子类继承这些共性,子类重写父类的方法,然后在此可以新增自己的属性和方法,以此标明差异活不同。

js为什么不是面向对象的编程语言呢?

用一句说明:

面向对象(Object-Oriented,OO)的语言有一个标志,那就是它们都有类的概念,而通过类可 以创建任意多个具有相同属性和方法的对象。前面提到过,ECMAScript中没有类的概念,因 此它的对象也与基于类的语言中的对象有所不同。所以js不是面向对象的语言。

ECMA-262把对象定义为:“无序属性的集合,其属性可以包含基本值、对象或者函数。”严格来讲, 这就相当于说对象是一组没有特定顺序的值。对象的每个属性或方法都有一个名字,而每个名字都映射 到一个值。正因为这样(以及其他将要讨论的原因),我们可以把 ECMAScript的对象想象成散列表:无 非就是一组名值对,其中值可以是数据或函数。

var person = new Object();
 person.name = "Nicholas";
 person.age = 29; 
 person.job = "Software Engineer"; 
 
person.sayName = function(){   
  alert(this.name); 
 }; 
 

 

上面的例子创建了一个名为 person 的对象,并为它添加了三个属性(name、age 和 job)和一个 方法(sayName())。其中,sayName()方法用于显示 this.name(将被解析为 person.name)的值。 早期的 JavaScript开发人员经常使用这个模式创建新对象。几年后,对象字面量成为创建这种对象的首选 模式。前面的例子用对象字面量语法可以写成这样:

var person = {    
 name: "Nicholas",  
  age: 29,   
  job: "Software Engineer", 
 
    sayName: function(){  

       alert(this.name);   
  }

 };

 

(1)属性类型

ECMA-262第 5版在定义只有内部才用的特性(attribute)时,描述了属性(property)的各种特征。 ECMA-262定义这些特性是为了实现 JavaScript引擎用的,因此在 JavaScript中不能直接访问它们。为了 表示特性是内部值,该规范把它们放在了两对儿方括号中,例如[[Enumerable]]。尽管 ECMA-262 第 3版的定义有些不同,但本书只参考第 5版的描述。 ECMAScript中有两种属性:数据属性和访问器属性。

a.数据属性

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

 [[Configurable]]:表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特 性,或者能否把属性修改为访问器属性。像前面例子中那样直接在对象上定义的属性,它们的 这个特性默认值为 true。

 [[Enumerable]]:表示能否通过 for-in 循环返回属性。像前面例子中那样直接在对象上定 义的属性,它们的这个特性默认值为 true。

 [[Writable]]:表示能否修改属性的值。像前面例子中那样直接在对象上定义的属性,它们的 这个特性默认值为 true。

 [[Value]]:包含这个属性的数据值。读取属性值的时候,从这个位置读;写入属性值的时候, 把新值保存在这个位置。这个特性的默认值为 undefined。 对于像前面例子中那样直接在对象上定义的属性,它们的[[Configurable]]、[[Enumerable]] 和[[Writable]]特性都被设置为 true,而[[Value]]特性被设置为指定的值。

var person = {  name: "Nicholas" }; 
 

b.访问器属性

访问器属性不包含数据值;它们包含一对儿 getter和 setter函数(不过,这两个函数都不是必需的)。 在读取访问器属性时,会调用 getter函数,这个函数负责返回有效的值;在写入访问器属性时,会调用 setter函数并传入新值,这个函数负责决定如何处理数据。访问器属性有如下 4个特性:

 [[Configurable]]:表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特 性,或者能否把属性修改为数据属性。对于直接在对象上定义的属性,这个特性的默认值为 true。

 [[Enumerable]]:表示能否通过 for-in 循环返回属性。对于直接在对象上定义的属性,这 个特性的默认值为 true。

 [[Get]]:在读取属性时调用的函数。默认值为 undefined。

 [[Set]]:在写入属性时调用的函数。默认值为 undefined。 访问器属性不能直接定义,必须使用 Object.defineProperty()来定义。

set和get方法作为java开发者再熟悉不过了。

var book = {   
  _year: 2004,   
   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

 

描述:

以上代码创建了一个 book 对象,并给它定义两个默认的属性:_year 和 edition。_year 前面 的下划线是一种常用的记号,用于表示只能通过对象方法访问的属性。而访问器属性 year 则包含一个 getter函数和一个 setter函数。getter函数返回_year 的值,setter函数通过计算来确定正确的版本。因此, 把 year 属性修改为 2005会导致_year 变成 2005,而 edition 变为 2。这是使用访问器属性的常见方 式,即设置一个属性的值会导致其他属性发生变化。 

补充说明:

不一定非要同时指定 getter和 setter。只指定 getter意味着属性是不能写,尝试写入属性会被忽略。 在严格模式下,尝试写入只指定了 getter 函数的属性会抛出错误。类似地,只指定 setter 函数的属性也 不能读,否则在非严格模式下会返回 undefined,而在严格模式下会抛出错误。 

在java中get和set是必须一同存在的,当然也可以不存在,前提是属性必须为非私有和默认,必须为公共的,即public。否则无法调用该属性。

 

(2)定义多个属性

由于为对象定义多个属性的可能性很大,ECMAScript 5 又定义了一个 Object.definePro- perties()方法。利用这个方法可以通过描述符一次定义多个属性。这个方法接收两个对象参数:第一 个对象是要添加和修改其属性的对象,第二个对象的属性与第一个对象中要添加或修改的属性一一对 应。

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

 

(3)读取属性特性

使用 ECMAScript 5的 Object.getOwnPropertyDescriptor()方法,可以取得给定属性的描述 符。这个方法接收两个参数:属性所在的对象和要读取其描述符的属性名称。返回值是一个对象,如果 是访问器属性,这个对象的属性有 configurable、enumerable、get 和 set;如果是数据属性,这 个对象的属性有 configurable、enumerable、writable 和 value。

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, "yea

 

 

作为java的开发者很容易理解对象。这个概念。不过如果是初学者的话对此往往头有点大。

因此记得一位朋友说过,学java的时候最好先是从前端html,css,js这样的学,因为学到js的时候存在一个对象的概念,有助于理解java的面向对象和比较。

当然,反过来java的话,也可以方便比较。

对象,这个概念,博大精深啊!

想起对象这个概念,我想起了伟大的spring,有了spring,再也不怕对象管理和操控问题。

因为spring有控制反转的概念,可以帮我们进行对象管理。但是js没有。

调侃一句,记得某个笑话讲过,程序员最怕什么?不懂这个是笑话的人肯定会讲最怕出bug。其实这个说的也是有道理的。

不过最终的答案是,程序员最怕找不到对象,作为java程序员,java称之为面向对象的编程语言,如果找不到对象,那还有什么意思呢?

玩笑一下,程序员有的时候还是得自我调侃调侃一下。有助于身心放松。

目录
相关文章
|
14天前
|
JavaScript
JS 获取对象数据类型的键值对的键与值
JS 获取对象数据类型的键值对的键与值
|
24天前
|
JavaScript 前端开发
Math对象:JavaScript中的数学工具
Math对象:JavaScript中的数学工具
27 1
N..
|
1月前
|
存储 JavaScript 前端开发
JavaScript中的对象
JavaScript中的对象
N..
10 0
|
1月前
|
JavaScript 前端开发
JavaScript对象系列(菜菜出品,必看!!!)
JavaScript对象系列(菜菜出品,必看!!!)
|
17天前
|
JavaScript 算法
原生JS完成“一对一、一对多”矩形DIV碰撞检测、碰撞检查,通过计算接触面积(重叠覆盖面积)大小来判断接触对象DOM
原生JS完成“一对一、一对多”矩形DIV碰撞检测、碰撞检查,通过计算接触面积(重叠覆盖面积)大小来判断接触对象DOM
|
1月前
|
存储 JavaScript 前端开发
在JavaScript中,对象和数组是如何进行扩展的?
在JavaScript中,对象和数组是如何进行扩展的?
22 4
|
2天前
|
存储 JavaScript 索引
js开发:请解释什么是ES6的Map和Set,以及它们与普通对象和数组的区别。
ES6引入了Map和Set数据结构。Map的键可以是任意类型且有序,与对象的字符串或符号键不同;Set存储唯一值,无重复。两者皆可迭代,支持for...of循环。Map有get、set、has、delete等方法,Set有add、delete、has方法。示例展示了Map和Set的基本操作。
16 3
|
3天前
|
JavaScript 前端开发 测试技术
学习JavaScript
【4月更文挑战第23天】学习JavaScript
11 1
|
3天前
|
JavaScript 前端开发 开发者
JavaScript中的错误处理:try-catch语句与错误对象
【4月更文挑战第22天】JavaScript中的错误处理通过try-catch语句和错误对象实现。try块包含可能抛出异常的代码,catch块捕获并处理错误,finally块则无论是否出错都会执行。错误对象提供关于错误的详细信息,如类型、消息和堆栈。常见的错误类型包括RangeError、ReferenceError等。最佳实践包括及时捕获错误、提供有用信息、不忽略错误、利用堆栈信息和避免在finally块中抛错。
|
9天前
|
JavaScript
【Js】检查Date对象是否为Invalid Date
【Js】检查Date对象是否为Invalid Date
13 0