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


    众说周知,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称之为面向对象的编程语言,如果找不到对象,那还有什么意思呢?

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

  • 相关阅读:
    关于SQL Server将一列的多行内容拼接成一行的问题讨论
    Win7 disk.sys无法加载的问题
    mvel2.0语法指南
    让网页不被缓存的解决办法
    让html页面不缓存js的实现方法
    mysql中间件研究(tddl atlas cobar sharding-jdbc)
    jdk环境变量设置理解
    the import cannot be resolved
    Oracle解除表锁定问题
    windows系统中软件开发常用的软件
  • 原文地址:https://www.cnblogs.com/youcong/p/9073583.html
Copyright © 2020-2023  润新知