欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

解析JavaScrip之对象属性

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

       对于面向对象编程语言(如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对象及其属性。如果要类比,那应该是这样的关系:

 解析JavaScrip之对象属性

   

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


 (一)函数表达式方式

  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

解析JavaScrip之对象属性
   //定义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

解析JavaScrip之对象属性
  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()方法,通过该方法,可以取得属性特性值,该方法的原型如下:

解析JavaScrip之对象属性

       其包含两个参数(对象和对象属性),其返回值是一个对象,如果是访问器属性,则这个对象的属性有[[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()函数来为对象定义属性,这种方式是在对象外部为对象定义属性,当然,也可以在对象内部为对象定义属性(访问器属性不可在对象内部定义,只能在外部定义)

解析JavaScrip之对象属性
//定义对象
    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

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

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

解析JavaScrip之对象属性
   //数据属性
    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可修改,修改成功

解析JavaScrip之对象属性
    //定义对象
    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属性,删除失败

解析JavaScrip之对象属性
   //定义对象
    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属性,删除成功

解析JavaScrip之对象属性
    //定义对象
    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,就再也不可改变。

 解析JavaScrip之对象属性

 解析JavaScrip之对象属性[[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。
  • 可以转载该博客,但必须著名博客来源。