zoukankan      html  css  js  c++  java
  • 解析JavaScrip之对象属性

           对于面向对象编程语言(如java,.net,php,python等)来说,其最大的特点在于“面向对象”,而"面向对象"较为显著的特征便是:封装,继承,多态。借助”面向对象“的这些特征,通常地,一个类大致包括三大部分:属性,方法和索引器,下面定义的一个类就包括这三大部分(.Net 语言)。

    public class OOClass
        {
            //定义属性
            private string _IDCard = "";
            private string _UserName = "";
    
            //定义方法
            public string GetIDCard()
            {
                return _IDCard;
            }
            public string GetUserName()
            {
                return _UserName;
            }
    
            //定义索引器
            private string Tel { get; set; }
        }

           我们知道,JavaScript是一门”弱面向对象“编程语言,其没有”对象“和”类“(注意:我们说JavaScript一切皆对象,这里的对象与面向对象编程语言的对象含义是不同的),类是实现继承的主要技术,对象是类的实例化,如果JavaScript要想实现继承,则首先要具备类和对象的条件,只有具备了该条件,方可实现继承(其实我们知道,JavaScript的原型和原型链实现继承,我会在后面的文章中深入分析原型与原型链),那么,在JavaScript中,是 什么扮演类和对象角色呢?JavaScript对象及其属性。如果要类比,那应该是这样的关系:

     

       

    一  两种典型的对象定义方式


     (一)函数表达式方式

      1.定义一个Person对象

        //定义Person对象
        function Person() {
           
        }

      2.为Person对象定义属性 

        //为person对象定义属性
        Person._tel = "136xxx954xx";
        Person.name = "Alan_beijing";
        Person.sex = "Man";
        Person.Address = "Shanghai";

      3.为对象定义方法  

        //为person对象定义方法
        Person.tel = function () {
            return this._tel;
        }

      4.测试结果    

        //测试
        alert(Person.name + "," + Person.sex + "," + Person.Address + "," + Person._tel);//Alan_beijing,Man,Shanghai,136xxx954xx
        alert(Person.SpeakLanguage());//Chinese And English

     5.完整例子Code

       //定义Person对象
        function Person() {
           
        }
        //为person对象添加属性
        Person._tel = "136xxx954xx";
        Person.name = "Alan_beijing";
        Person.sex = "Man";
        Person.Address = "Shanghai";
        //为person对象添加方法
        Person.tel = function () {
            return this._tel;
        }
    
        //测试
        alert(Person.name + "," + Person.sex + "," + Person.Address);//Alan_beijing,Man,Shanghai
        alert(Person.tel());//136xxx954xx
    View Code

    (二)对象字面量方式

     1.定义对象同时为对象定义属性和方法

      var Person = {
            //为person对象定义属性
            _tel: "136xxx954xx",
            name: "Alan_beijing",
            sex: "Man",
            address: "Shanghai",
            //为person对象定义方法
            tel: function () {
                return this._tel;
            }
        }

     2.测试结果

        //测试
        alert(Person.name + "," + Person.sex + "," + Person.address);//Alan_beijing,Man,Shanghai
        alert(Person.tel());//136xxx954xx

     3.完整例子Code

      var Person = {
            //为person对象添加属性
            _tel: "136xxx954xx",
            name: "Alan_beijing",
            sex: "Man",
            address: "Shanghai",
            //为person对象添加方法
            tel: function () {
                return this._tel;
            }
        }
    
        //测试
        alert(Person.name + "," + Person.sex + "," + Person.address);//Alan_beijing,Man,Shanghai
        alert(Person.tel());//136xxx954xx
    View Code

     (三)两种方式比较

       在两种典型的对象定义方式中,对象字面量定义方式是比较常用的,其常用根本原因是其采用json的格式,简洁而不繁琐

    二 对象属性种类


          对象属性,从属性特性上来划分,大致可分为两大类,即数据属性和访问器属性。

     (一)数据属性

          数据属性具有四个基本特性,即[[Configurable]],[[Enumerable]],[[Writable]]和[[value]]。

        (1)[[Configurable]]:布尔类型(true或false,默认值为true),表示能否对对象属性进行操作,大致包括如下操作:

    • 删除属性
    • 修改属性特性
    • 修改属性类型,如将数据属性修改为访问器属性    

       (2)[[Enumerable]]:能否通过for..in..循环遍历

       (3)[[Writable]]:能否修改属性值

       (4)[[value]]:属性值

    (二)访问器属性

          访问器属性具有四个基本特性,即[[Configurable]],[[Enumerable]],[[Get]]和[[Set]]。

       (1)[[Configurable]]:布尔类型(true或false),表示能否对对象属性进行操作,大致包括如下操作:

    • 删除属性
    • 修改属性特性
    • 修改属性类型,如将数据属性修改为访问器属性    

       (2)[[Enumerable]]:能否通过for..in..循环遍历

       (3)[[Get]]:对象向外提供访问对象属性的函数

       (4)[[Set]]:对象向外提供设置对象属性的函数

     (三)读取数据的特性

           ECMAScript 5提供了Object.getOwnPropertyDescriptor()方法,通过该方法,可以取得属性特性值,该方法的原型如下:

           其包含两个参数(对象和对象属性),其返回值是一个对象,如果是访问器属性,则这个对象的属性有[[Configurable]],[[Enumerable]],[[Get]],[[Set]];若对象属性为数据属性,则返回[[Configurable]],

    [[Enumerable]],[[writable]]和[[value]]。 下列代码,先定义一个对象Person,然后通过ECMAScript 5提供的函数defineProperties()为该对象添加四个数据属性(_tel,name,sex和address)和一个访问器属

    性(telephone),其中telephone访问器属性具有两个函数set()和get(),然后,我们通过getOwnPropertyDescriptor()函数访问它们的四个特性值。

        //定义对象
        var Person = {
    
        }
        //为对象添加属性
        Object.defineProperties(Person, {
            //为person对象添加属性
            _tel: {
                value: "136xxx954xx"
            },
            name: {
                value: "Alan_beijing"
            },
            sex: {
                value: "Man"
            },
            address: {
                value: "Shanghai"
            },
            //访问器
            telephone: {
                get: function () {
                    //var strName = "name:" + name;
                    //return strName;
                    return this._tel;
                },
                set: function (tel) {
                    _tel = tel;
                }
            }
        })
    
        //数据属性
        var dataProp = Object.getOwnPropertyDescriptor(Person, "_tel");
        alert(dataProp.value);//136xxx954xx
        alert(dataProp.configurable);//false
        alert(dataProp.writable);//false
        alert(dataProp.enumerable);//false
        //访问器属性
        var visitProp = Object.getOwnPropertyDescriptor(Person, "telephone");
        alert(visitProp.configurable);//false
        alert(visitProp.enumerable);//false
        alert(typeof visitProp.get);//function
        alert(typeof visitProp.set);//function

        我们再来看看下面例子:下面例子与上面例子有几点区别:

        区别1:上面的属性通过defineProperties()定义在对象Person外,而下面Person对象属性都是定义在对象Persin内部的

        区别2:结果不同,对于数据属性,除了[[value]]相同外,其他三个特性([[Configurable]],[[Writble]],[[Enumerable]])恰好是相反的的(上面均为false,下面均为true);对于访问器属性,除[[Configurable]]和[[Enumerable]]

                     属性值相反外,上面代码[[Get]]和[[Set]]能成功访问,但是下面代码显示undefined,说明索引器属性不能在对象内部定义

        //定义对象
        var Person = {
            _tel: "136xxx954xx",
            name: "Alan_beijing",
            sex: "Man",
            telephone: {
                get: function () {
                    //var strName = "name:" + name;
                    //return strName;
                    return this._tel;
                },
                set: function (tel) {
                    _tel = tel;
                }
            }
        }
    
        //数据属性
        var dataProp = Object.getOwnPropertyDescriptor(Person, "_tel");
        alert(dataProp.value);//136xxx954xx
        alert(dataProp.configurable);//true
        alert(dataProp.writable);//true
        alert(dataProp.enumerable);//true
    
        //访问器属性
        var visitProp = Object.getOwnPropertyDescriptor(Person, "telephone");
        alert(visitProp.configurable);//true
        alert(visitProp.enumerable);//true
        alert(typeof visitProp.get);//undefined
        alert(typeof visitProp.set);//undefined

    总结:

        1.可以通过defineProperties()函数为对象定义多个属性;

        2.访问器属性不能在对象内部定义,只能在对象外部定义;

        3.在对象内部定义属性与通过defineProperties()函数在对象外部定义,属性特性值是相反的;

        4.通过getOwnPropertyDescriptor()函数可以访问对象属性;

        5.需要注意的是,访问器属性的[[Get]]和[[Set]]不是必须的;

    三  对象属性基本操作


     (一)添加定义属性

         ECMAScript提供了definePropertie()和defineProperties()函数来为对象定义属性,这种方式是在对象外部为对象定义属性,当然,也可以在对象内部为对象定义属性(访问器属性不可在对象内部定义,只能在外部定义)

    //定义对象
        var Person = {
    
        }
        //为对象添加属性
        Object.defineProperties(Person, {
            //为person对象添加属性
            _tel: {
                value: "136xxx954xx"
            },
            name: {
                value: "Alan_beijing"
            },
            sex: {
                value: "Man"
            },
            address: {
                value: "Shanghai"
            },
            //访问器
            telephone: {
                get: function () {
                    //var strName = "name:" + name;
                    //return strName;
                    return this._tel;
                },
                set: function (tel) {
                    _tel = tel;
                }
            }
        })
    View Code

     (二)访问对象属性的四个特性

         如下为在对象外部定义属性的访问结果,内部定义访问结果是相反的

       //数据属性
        var dataProp = Object.getOwnPropertyDescriptor(Person, "_tel");
        alert(dataProp.value);//136xxx954xx
        alert(dataProp.configurable);//false
        alert(dataProp.writable);//false
        alert(dataProp.enumerable);//false
        //访问器属性
        var visitProp = Object.getOwnPropertyDescriptor(Person, "telephone");
        alert(visitProp.configurable);//false
        alert(visitProp.enumerable);//false
        alert(typeof visitProp.get);//function
        alert(typeof visitProp.set);//function
    View Code

     (三)删除/修改对象属性

          如下代码,我们设置数据属性address可修改,修改成功

        //定义对象
        var Person = {
    
        }
        //为对象添加属性
        Object.defineProperties(Person, {
            //为person对象添加属性
            _tel: {
                value: "136xxx954xx"
            },
            name: {
                value: "Alan_beijing"
            },
            sex: {
                value: "Man"
            },
            address: {
                writable: true, 
                value: "Shanghai"
            },
            //访问器
            telephone: {
                get: function () {
                    //var strName = "name:" + name;
                    //return strName;
                    return this._tel;
                },
                set: function (tel) {
                    _tel = tel;
                }
            }
        })
    
    
        alert(Person.address);//Shanghai
        Person.address = "Beijing";
        alert(Person.address);//Beijing
    View Code

          如下代码,我们先设置[[Configurable]] 只可读(false),然后尝试删除address属性,删除失败

       //定义对象
        var Person = {
    
        }
        //为对象添加属性
        Object.defineProperties(Person, {
            //为person对象添加属性
            _tel: {
                value: "136xxx954xx"
            },
            name: {
                value: "Alan_beijing"
            },
            sex: {
                value: "Man"
            },
            address: {
                configurable: false,
                writable: true, 
                value: "Shanghai"
            },
            //访问器
            telephone: {
                get: function () {
                    //var strName = "name:" + name;
                    //return strName;
                    return this._tel;
                },
                set: function (tel) {
                    _tel = tel;
                }
            }
        })
    
    
        alert(Person.address);//Shanghai
        delete Person.address;
        alert(Person.address);//Shanghai
    View Code

          如下代码,我们先设置[[Configurable]]  可操作(true),然后再删除address属性,删除成功

        //定义对象
        var Person = {
    
        }
        //为对象添加属性
        Object.defineProperties(Person, {
            //为person对象添加属性
            _tel: {
                value: "136xxx954xx"
            },
            name: {
                value: "Alan_beijing"
            },
            sex: {
                value: "Man"
            },
            address: {
                configurable: true,
                writable: true, 
                value: "Shanghai"
            },
            //访问器
            telephone: {
                get: function () {
                    //var strName = "name:" + name;
                    //return strName;
                    return this._tel;
                },
                set: function (tel) {
                    _tel = tel;
                }
            }
        })
    
    
        alert(Person.address);//Shanghai
        delete Person.address;
        alert(Person.address);//Undefined
    View Code

      注意:当一旦定义[[Configurable]]为false时,再也变不回去了

        //定义对象
        var Person = {
    
        }
        //为对象添加属性
        Object.defineProperties(Person, {
            //为person对象添加属性
            _tel: {
                value: "136xxx954xx"
            },
            name: {
                value: "Alan_beijing"
            },
            sex: {
                value: "Man"
            },
            address: {
                configurable: false,
                writable: true, 
                value: "Shanghai"
            },
            //访问器
            telephone: {
                get: function () {
                    //var strName = "name:" + name;
                    //return strName;
                    return this._tel;
                },
                set: function (tel) {
                    _tel = tel;
                }
            }
        })
    
        Object.defineProperty(Person, "address", {
            configurable:true
        }) 

      上述代码先将addess属性的特性[[configurable]]设置false,然后又将其修改为true,修改失败,因为[[configurable]]特性一旦设置为false,就再也不可改变。

     

     [[configurable]]和[[writable]]区别?

         前者操作属性特性,如删除属性,修改属性,更改属性类型;后者操作属性值,如更改属性值。两者没有直接关系,即不管[[configurable]]的值是怎样,一个属性的值能否可修改,是由[[writable]]决定的,而不受[[configurable]]影响。

    四  参考文献


     【01】JavaScript 高级程序设计(第三版)   (美)Nicholas C.Zakas 著       李松峰   曹力  译

    【02】JavaScript 权威指南 (第6版)    David  Flanagan 著

    五  已发布文章


    1. JavaScript之函数(上)
    2. 浅析JavaScript之数组
    3. 浅谈JavaScript之事件(上)
    4. 解析JavaScrip之属性

    六  版权区


    • 感谢您的阅读,若有不足之处,欢迎指教,共同学习、共同进步。
    • 博主网址:http://www.cnblogs.com/wangjiming/。
    • 极少部分文章利用读书、参考、引用、抄袭、复制和粘贴等多种方式整合而成的,大部分为原创。
    • 如您喜欢,麻烦推荐一下;如您有新想法,欢迎提出,邮箱:2098469527@qq.com。
    • 可以转载该博客,但必须著名博客来源。
  • 相关阅读:
    Golang学习开篇——Go语言优势
    Ubuntu —— 查看和开放端口
    mysql——sql语句
    python模块——xlwt
    字典容器类型使用之坑
    pandas——将sql查询结果,分几部分存入excel
    pandas 点击 excel 表格数据,跳转到 sheet2
    datetime——计算前一天的这个时间 坑
    报错总结
    nginx——部署前端
  • 原文地址:https://www.cnblogs.com/wangjiming/p/10191687.html
Copyright © 2011-2022 走看看