首页 > 技术文章 > JavaScript高级程序设计(第三版)第六章 面向对象的程序设计

fashion1993 2014-10-14 20:14 原文

6.1 理解对象

 

 

var person = new Object();
person.name = "Nicholas";
person.age = 29;
person.job = "Software Engineer";
person.sayName = function(){
alert(this.name);
};

person.sayName();

6.1.1 属性类型

1.数据属性

  • [[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。
  • [[Enumerable]]:表示能否通过for-in循环返回属性。
  • [[Writable]]:表示能否修改属性的值。
  • [[Value]]:包含这个属性的数据值。读取属性值的时候,从这个位置读;写入属性的时候,把新值保存在这个位置。默认值为undefined

2.访问器属性

  • [[Configureable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为数据属性。
  • [[Enumerable]]:表示能否通过for-in循环返回属性。
  • [[Get]]:在读取属性时调用的函数。默认值为undefinded。
  • [[Set]]:在写入属性是调用的函数。默认值为undefinded。

6.1.2 定义多个属性

        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;
                    }                  
                }            
            }        
        });
           
        book.year = 2005;
        alert(book.edition);   //2

 

6.1.3 读取属性的特性

        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, "year");
        alert(descriptor.value);          //undefined
        alert(descriptor.enumerable);     //false
        alert(typeof descriptor.get);     //"function"

 

6.2.1 工厂模式

        function createPerson(name, age, job){
            var o = new Object();
            o.name = name;
            o.age = age;
            o.job = job;
            o.sayName = function(){
                alert(this.name);
            };    
            return o;
        }
        
        var person1 = createPerson("Nicholas", 29, "Software Engineer");
        var person2 = createPerson("Greg", 27, "Doctor");
        
        person1.sayName();   //"Nicholas"
        person2.sayName();   //"Greg"

 

6.2.2 构造函数模式

        function Person(name, age, job){
            this.name = name;
            this.age = age;
            this.job = job;
            this.sayName = function(){
                alert(this.name);
            };    
        }
        
        var person1 = new Person("Nicholas", 29, "Software Engineer");
        var person2 = new Person("Greg", 27, "Doctor");
        
        person1.sayName();   //"Nicholas"
        person2.sayName();   //"Greg"
        
        alert(person1 instanceof Object);  //true
        alert(person1 instanceof Person);  //true
        alert(person2 instanceof Object);  //true
        alert(person2 instanceof Person);  //true
        
        alert(person1.constructor == Person);  //true
        alert(person2.constructor == Person);  //true
        
        alert(person1.sayName == person2.sayName);  //false    

 

6.2.3 原型模式

        function Person(){
        }
        
        Person.prototype.name = "Nicholas";
        Person.prototype.age = 29;
        Person.prototype.job = "Software Engineer";
        Person.prototype.sayName = function(){
            alert(this.name);
        };
        
        var person1 = new Person();
        person1.sayName();   //"Nicholas"
        
        var person2 = new Person();
        person2.sayName();   //"Nicholas"
      
        alert(person1.sayName == person2.sayName);  //true
        
        alert(Person.prototype.isPrototypeOf(person1));  //true
        alert(Person.prototype.isPrototypeOf(person2));  //true
        
        //only works if Object.getPrototypeOf() is available
        if (Object.getPrototypeOf){
            alert(Object.getPrototypeOf(person1) == Person.prototype);  //true
            alert(Object.getPrototypeOf(person1).name);  //"Nicholas"
        }

 

1.       理解原型

无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性。在默认的情况下,所有prototype属性都会自动获得一个constructor属性,这个属性包含一个指向prototype属性函数的指针。

2.       原型与in操作符

两种使用in操作符的场合:单独使用或for-in循环中

单独使用:in操作符会在通过对象能够访问给定属性时返回true

3.       更简单的原型语法

function Person(){}

Person.prototype = {

           name: ‘Nicholas’,

           age: 29,

           sayName: function(){

                    alert(this.name);

           }

}

4.       原型的动态性

重写原型会切断现有原型与任何之前已经存在的对象实例之间的联系,虽然它们引用的仍然是最初的原型

5.       原生对象的原型

可以扩展原生对象的方法

String.prototype.startWith = function(){

         return this.indexOf(text) == 0;

}

var msg = ‘hello world’;

alert(msg.startWith(‘hello’)); //output true

6.       原型对象的问题

原型中所有属性被很多的实例共享,对于包含引用类型的属性来说,就不怎么乐观。

6.3.1 原型链

原型链实现继承的原理:利用原型让一个引用类型继承另一个引用类型的属性和方法。回顾一个构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么假如我们让原型对象等于另一个类型的实现,结果会怎么样呢?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系成立。如此层层递进,就构成了实例与原型的链条。

 

推荐阅读