《javascript面向对象精要》总结(三)

构造函数和原型对象

构造函数:就是使用new创建对象时调用的函数,然而构造函数也是函数,可以用定义函数的方法定义它,唯一的区别是构造函数的函数名首字母应该大写,用此来与其他函数进行区别。

function Person(){
    //空的构造函数
}
var person1 = new Person;    //若没有需要传递给构造函数的参数,括号可以省略。

//person1是Person的一个实例,可以使用instanceof操作符获取对象的类型,每个对象在创建的时候都自动拥有一个构造函数属性,其中包含了一个指向其构造函数的引用。

console.log(person1 instanceof Person);        //true

//通过对象字面形式或Object构造函数创建出来的泛用对象,其构造函数属性只想Object,那些通过自定义构造函数创建出来的对象,其构造函数指向创建它的构造函数。

console.log(person1.constructor=== Person);        //true

很明显,空的构造函数没有什么卵用,使用构造函数的目的是为了创建许多拥有相同属性和方法的对象,你需要做的事在构造函数内给this添加属性:

function Person(name){
    this.name = name;
    this.sayName = function(){
        console.log(this.name);
    };
}
var person = new Person("Shi");
console.log(person.name);    // "Shi"
person.sayName();    // "Shi"

构造函数本身不需要返回值,new会帮你返回,你也可以在构造函数中显示调用return。如果返回的值是一个对象,它会替代新创建的对象实例返回,如果返回值是一个原始类型,它会被忽略。尽量使用new调用构造函数,不然有可能改变全局变量。

但是如果我们初始化好多个Person类的实例对象,那么每一个对象都有一个name属性和一个sayName()方法,存在代码冗余,而原型就帮我们实现了所有对象实例共享一个方法,是同this来访问正确的数据。

function Person(name){
    this.name = name;
}
Person.prototype.sayName = function(){
    console.log(this.name);
}
//原型是javascript实现继承的基础,之前的文章有过记录,这里就不再多解释了。
//但是当使用对象的字面形式改写原型对象改变了构造函数的属性,使他指向Object而不是你创建的类。这是因为原型对象具有一个constructor属性,这是其他对象没有的。当一个函数被创建时,它的prototype属性也被创建,而该原型对象的constructor属性指向该函数。所以我们需要这样去写:

Person.prototype = {
    constructor:Person,
    sayName : function(){
        console.log(this.name);
    }
};

可以发现对象和构造函数之间没有直接的联系,不过对象实例和原型对象以及原型对象和构造函数之间有直接的联系。

对象模式

javascript对象的所有属性都是公有的,但是有时你可能不希望数据公有。

模块模式:看看下面的代码

var yourObject = (function(){

    //private data

    return {
        //public method and properties
    };
}());
//这种语法会立即执行这个匿名函数,也就是函数仅存在于被调用的瞬间,执行之后就被销毁了。

模块模式实现了使用普通变量作为私有变量,并且通过创建闭包函数作为对象方法来操作他们:

var person = (function(){
    var age = 25;
    return {
        name : "Shi",
        getAge : function(){
            return age;
        },
        growOlder : function(){
            age++;
        }
    };
}());

console.log(person.name);
console.log(person.getAge());
person.age = 100;
console.log(person.getAge());
person.growOlder();
console.log(person.getAge());

构造函数的私有成员:

var Person = (function(){
    //所有对象的实例都共享这个age
    var age = 25;
    function InnerPerson(name){
        this.name = name;
    }
    InnerPerson.prototype.getAge = function(){
        return age;
    }
    InnerPerson.prototype.growOlder = function(){
        age++;
    }
    return InnerPerson;
}());
var person = new Person('Shi');
console.log(person.name);
console.log(person.getAge());
person.age = 100;
console.log(person.getAge());
person.growOlder();
console.log(person.getAge());