• 第八章 面向对象之一:对象的理解


    js的面向对象概念跟C++、Java不太一样,更像是一个精简版的设计(可能是因为语言设计者本身讨厌面向对象随便为了应付弄出来一个?还是为了减轻浏览器的负担才这么设计,我觉的是第二者哦,毕竟解释型程序没有编译型程序效率高)。

    ECMAScript对对象的定义:”无需属性的集合,其属性可以包含基本值、对象或者函数“。等等,这句话眼熟啊,想起来了吧,Object类型就是这么定义的啊。所以,Object类型就是js里所有对象(类)的父类。

    而所有通过new Array、new String的变量都是Array类String类的实例,当然Array、String类的父类也都是Object。

    我们知道,做为一个对象,要有属性和方法,js里创建自定义对象的主流方法是字面量方法,如下:

    <script>
    //这实际是Object的一个实例
    var Mouse = {  
        name : "老鼠",
        sayHello : function () {
            alert("吱吱吱");
        }
    }
    Mouse.sayHello();
    </script>

    相当于:

    var Mouse = new Object();  //创建Object的实例
    Mouse.name = "老鼠";
    Mouse.sayHello = function () {
        alert("吱吱吱");
    }
    
    Mouse.sayHello();

    但是这种字面型创建实例的方法,除了做为配置文件外其实我觉的没什么用,因为在创建实例的时候,我们一般需要传入参数进去,建立自己的类,并通过类创建实例更加有用,后续再介绍。Mouse对象有一个name属性和一个sayHello()方法,在js中,制造属性的方法有两种,一种是“赋值”、一种是“定义”。

    “制造(或修改)"一个新(或者已经存在)的属性,赋值的方法就是我们上边代码内用的方法,定义的方法是通过Object.defineProperty()函数实现的,用法为Object.defineProperty(对象,属性名,配置文件);,后边我们会举例说明。

    通过赋值和定义方法制造出来的属性会有不同,主要表现在:

    • 定义方法:对象如果本身已经存在了这个属性,则修改,如果不存在则新定义。只针对本身对象操作。
    • 赋值方法:如果对象本身存在这个属性,则修改,如果不存在,会根据原型链往上找,如果找不到,则在对象本身上进行属性制造,如果找到了,那就麻烦大了。。。。。(这篇博文看了都不用看我这个,我这个只是为了总结学习用。http://www.cnblogs.com/ziyunfei/archive/2012/10/31/2738728.html)

    所以区别就是,定义方法制造属性只针对当前对象本身操作,而赋值会进行原型链查找。

    在js里,属性的分类有三种:数据属性访问器属性、内部属性,他们的区别如下:

    • 数据属性:拥有确定值的属性。
    • 访问器属性:配置了getter和setter的数据属性。
    • 内部属性:javaScript引擎内部使用的属性,比如原型属性等。

    也就是说,实际上name属性是还有属性的,它的属性是定义了它属性本身的一些特点。也就是说,数据属性和访问器属性是可以配置的,具体来说,他们两个各自有四个属性(其中有两个是共同的),也就是数据属性和访问器属性都各自有两个特性属性,还有两个公用属性

    共用属性:

    • [[Configurable]]:能否通过delete删除从而重新定义属性。
    • [[Enumerable]]:能否通过for-in循环返回属性。

    数据属性特有属性:

    • [[Writeable]]:能否修改属性的值。
    • [[Value]]:包含这个属性的数据值。读取属性值的时候从这里读取,写入的时候写入到这里,默认为undefined。

    访问器属性特有属性:

    • [[Get]]: 存储着getter方法。
    • [[Set]]: 存储着setter方法。

    下面举例通过Object.defineProperty()方法设置属性如下(其他属性设置也是如此,但是可以一次性设置多个属性):

    <script>
    //这实际是Object的一个实例
    var Mouse = {  
        name : "老鼠",
        sayHello : function () {
            alert("吱吱吱");
        },
        sayName : function () {
            alert(this.name);
        }
    };
    Object.defineProperty(Mouse,"name",{
        writable:false,  //设置Mouse实例的name属性不能修改值
        value:"耗子"  //但是此处还是可以的,需要{}里的运行完才起作用?这里不清楚
    });
    Mouse.name = "耗子1";  //并没有什么用
    Mouse.sayName();  //耗子
    </script>

     这是数据属性定义的方法,我们定义了一个已经存在的属性,所以JS就直接重写了name属性,如果我们定义一个age属性,则会新增加一个age属性,大家理解一下。下面写一段访问器属性的get、set方法:

    <script>
    //这实际是Object的一个实例
    var Mouse = {  
        name : "老鼠",
        sayHello : function () {
            alert("吱吱吱");
        },
        sayName : function () {
            alert(this.name);
        }
    };
    
    Object.defineProperty(Mouse,"age",{  //通过定义方法增加了一个新的访问器属性,名字为age,age的getter是get函数,setter是set函数
        get : function () {  //
            alert("getter接口");
            return this.name;
        },
        set : function (ages) {  //赋值操作会通过set函数执行。
            alert("setter接口");
            if (ages>10)    {
                this.name = "大耗子";
            }
            else {
                this.name = "小耗子";
            }
        }
    });
    Mouse.age = 123;  //通过set函数对age进行赋值
    alert(Mouse.age);  //通过get函数进行读取  显示123
    </script>

    所以我认为,如果你给属性设置了get或者set函数,那么他就是访问器属性,如果不设置,就是数据属性。当然,定义访问器属性的时候是无法使用数据属性的value值的,这也是区别吧,主要在方式方法上的区别。

    那么,如何取得一个属性的特性呢,在ECMAScript5里,有一个Object.getOwnPropertyDescriptor()方法,它有两个参数,属性所在的对象和属性名。

    接上边继续编码:

    var a = Object.getOwnPropertyDescriptor(Mouse,"age");
    console.dir(a);
    a = Object.getOwnPropertyDescriptor(Mouse,"name");
    console.dir(a);

    结果如下:

    当然,还可以一次性设置多个属性,用Object.definePropertys(),具体用法google吧。顺便说一下,貌似对象(实例)的方法应该也是可以通过定义和赋值进行制造的!

  • 相关阅读:
    CSS相关知识点
    嵌入式经典面试题
    代码阅读——十个C开源项目
    2020年3月编程语言排行
    C++题目
    英文符号对照大全
    详解Sort函数降序排序-c++
    C/C++语言学习资料,原创
    Bootstrap组件之响应式导航条
    Boostrap全局CSS样式
  • 原文地址:https://www.cnblogs.com/jingubang/p/4633326.html
Copyright © 2020-2023  润新知