高程三 面向对象程序设计

 不包括原型部分 6.1.1~6.2.2

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
    <script>
        var obj = {
            name: "Harold",
            age: 21,
            job: "student",
            boolean: true,
            method: function test () {
                console.log(this.job);
            }
        }
        // console.log(obj.name);
        // obj.method();
        // for(i in obj){
        //     console.log(i);
        // }
        // //ECMAScript中的属性分为:数据属性、访问器属性
        // //数据属性:包含一个数据值的位置,在这个位置可以进行读取或写入值,用以下特性描述其行为
        // // [[Configurable]] 能否通过delete删除属性从而重新定义 能否修改属性特性 能否把属性修改为访问器属性
        // // [[Enumerable]] 能否通过for-in循环返回属性
        // // [[Writable]] 能否修改属性值 注意与第一个区分
        // // 直接在对象中定义的属性  前面三个默认为true
        // // [[Value]] 这个属性的数据值 默认为undefined
        // //只能使用Object.defineProperty()方法
        Object.defineProperty(obj, "name", {
            writable: false,
            // value: "linbudu"
        });
        obj.name = "linbudu";//把Writable改为false后会发现无法指定新的属性值了!
        console.log(obj.name);
        Object.defineProperty(obj,"name", {
            configurable:false,
            value: "budu",
        });
        console.log(obj.name);//budu
        // Object.defineProperty(obj,"name", {
        //     configurable:true,
        //     value: budu,
        // });//抛出错误:一旦把属性定为不可配置的,就无法再修改回去了 如果原先就是false还可以
        // //注意 当调用此方法创建一个新属性时 前三个特性的默认值都是false

        // //访问器属性 不包含数据值,而是包含getter(读取访问器属性时,负责返回有效的值)
        // //与setter(在写入访问器属性时调用setter并传入新值,由这个函数决定如何处理数据)函数
        //     // [[Configurable]] 能否通过delete删除属性从而重新定义 能否修改属性特性 能否把属性修改为访问器属性
        // // [[Enumerable]] 能否通过for-in循环返回属性
        var reward = {
            _year: 0,
            ward: 1000
        };
        Object.defineProperty(reward, "_year", {
            get: function(){
                return this._year;
            },
            set: function(newValue){
                if(newValue > 0){
                    this._year = newValue;
                    this.ward = (newValue - _year);
                }
            }
        });
        reward.year = 5;
        console.log(reward.ward);//5
        //_记号常常用于表示 只能通过对象方法访问的属性
        var obj2 = {};
        Object.defineProperties(obj2,{
            name: {
                writable: true,
                value: "joyce"
            },
            age:{
                configurable: true,
            }})
        console.log(obj2.name);

        //读取属性的特性
        var attr = Object.getOwnPropertyDescriptor(obj2,"name");
        console.log(attr.value);//joyce
        console.log(attr.configurable);//false 详见行48注释
        //可以对任何对象使用此方法
        var attr_window = Object.getOwnPropertyDescriptor(Document,"name");
        console.log(attr_window.configurable);//true~ yup!
        

        //创建对象
        //Object构造函数与字面量都可以用来创建单个对象,但这些方法使用同一个接口创建
        //多个对象,会产生大量的重复代码
        //工厂模式  用函数来封装以特定接口创建对象的细节
        function createObj(name,age,dream){
            var o = new Object;
            o.name = name;
            o.age = age;
            o.dream = dream;
            o.method = function(){
                alert("Having some Chicken's Blood!")
            };
            return o;//将o返回给要创建的对象
        }
        var day1 = createObj("Harold",21,"To be a Front-end development engineer");
        var day2 = createObj("Joyce","19","Not now~");
        console.log(day1.name);
        // day1.method();
        //解决了创建多个相似对象的问题,但没有解决对象识别的问题

        //构造函数模式
        // 创建自定义的构造函数  来定义自定义对象类型的属性与方法
        function  createFunc (name,age,job) {
            this.name = name;
            this.age = age;
            this.job = job;
            // this.method = Mom;
        }
        function Mom(){
            alert(this.name);
        }
        var day3 = new createFunc("budu",21,"student");
        console.log(day3.job);
        //注意:这里没有显式的创建对象  直接将属性与方法赋给了this对象  没有return语句
        //按照惯例  构造函数始终都应该以一个大写字母开头  构造函数本身也是函数 但可用来创建对象而已
        //使用new操作符创建createFunc的新实例过程包括:创建一个新对象{},将执行函数的作用域赋给这个新对象(则this指向这个新对象)
        //执行构造函数中的代码(添加属性和方法),返回新对象

        //使用这种方法创建的新对象包含着构造函数的不同实例 且都具有constructor属性  并指向createFunc
        console.log(day3.constructor);//返回构造函数的源代码
        //这些对象既是Object的实例(所有对象都继承自Object),也是createFunc的实例
        console.log(day3 instanceof Object);
        console.log(day2 instanceof Object);
        console.log(day3 instanceof createFunc);

        //在另一个对象的作用域中调用构造函数
        var obj3 = {
            name:"Harold",
            age:18,
            // job:none  这边有几个属性 下面call()就要传进去几个参数 否则会出错
        };
        createFunc.call(obj3,"Joyce",20);
        console.log(obj3.name);
        //在obj3的作用域中调用后 他就拥有了这些属性与方法

        //构造函数的主要问题:每个方法都要在每个实例上重新创建一遍  即:两个对象拥有的方法不是同一个Function对象的实例
        //不同实例上的同名函数并不相同
        //改进方法- 行118~122  这样一来,新创建的对象会共享在全局作用域中定义的同一个函数(引用类型的定义)
        //然而这个函数虽然定义在全局作用域中 但实际只能被某个对象调用  全局毫无意义 
        //并且如果对象需要定义许多方法  那么就要在全局作用域中定义多个全局函数  那么这个自定义的引用类型(注意这里说的是Function,
        //使用它作为方法这只是引用过程)
        

    </script>
</body>
</html>
原文地址:https://www.cnblogs.com/linbudu/p/10470868.html