日期:2014-05-16  浏览次数:20421 次

面向对象的JS(3) 对象创建和成员作用域
一 对象创建
1 使用new操作符
内置或自定义的对象类型的实例可以用new操作符创建。new操作符只运行构造函数,已存在的对象不能用new再创建一次。首先new操作符创建一个空对象;然后调用构造函数同时将新创建的对象赋值给this,构造函数执行其初始化工作。
//or var dog = {};
//or var dog = new MyDogType();
var dog = new Object();
dog.name = "Scooby";
dog.owner = {};
dog.owner.name = "Mike";
dog.bark = function () {
    return "Woof";
};
console.log(dog.name); // Scooby
console.log(dog.owner.name); // Mike
console.log(dog.bark()); // Woof

2 对象字面量创建
由对象字面量创建对象很容易,且可以创建嵌套对象。
 var dog = {
    name: "Scooby?",
    owner: {
        name: "Mike"
    },
    bark: function () {
        return" Woof";
    }
};
console.log(dog.name); // Scooby
console.log(dog.owner.name); // Mike
console.log(dog.bark()); // Woof

二 成员作用域
1 私有字段
在JavaScript中,没有内置的私有字段支持。但我们可以用封闭的构造函数来实现。定义于构造函数内的变量可以作为私有字段。任何使用私有字段的方法应该在构造函数内定义。请注意,原型方法不能在构造函数中声明和使用私有字段。私有的geter和setter方法应该在构造函数中声明。
function Customer() {
    // private field
    var risk = 0;
    this.getRisk = function () {
        return risk;
    };
    this.setRisk = function (newRisk) {
        risk = newRisk;
    };
    this.checkRisk = function () {
        if (risk > 1000)
            return" Risk Warning";
        return" No Risk";
    };
}
Customer.prototype.addOrder = function (orderAmount) {
    this.setRisk(orderAmount + this.getRisk());
    return this.getRisk();
};
var customer = new Customer();
console.log(customer.getRisk()); // 0
console.log(customer.addOrder(2000)); // 2000
console.log(customer.checkRisk()); // Risk Warning

2 私有方法
也称为"嵌套"或"内部函数"。私有方法定义在另一个函数内且不能从外部访问。私有方法可以在函数的任何部分声明。
function Customer(name) {
    var that = this;
    var risk = 0;
    this.name = name;
    this.type = findType();
    // private method
    function findType() {
        console.log(that.name);
        console.log(risk);
        return" GOLD";
    }
}

或者
function Customer(name) {
    var that = this;
    var risk = 0;
    this.name = name;
    // private method
    var findType = function () {
        console.log(that.name);
        console.log(risk);
        return" GOLD";
    };
    this.type = findType();
}
var customer = new Customer("ABC Customer"); // ABC Customer
// 0
console.log(customer.type); // GOLD
console.log(customer.risk); // undefined

如果一个私有内部函数返回给外部调用者,那么就可以从外部调用。
function Outer() {
    return new Inner();
    //private inner
    function Inner() {
        this.sayHello = function () {
            console.log('Hello');
        }
    }
}
(new Outer()).sayHello(); // Hello

3 特权方法
原型方法不能访问私有字段;原型方法都是pulbic的。我们需要一种方法来声明方法
(1)可以公共访问这些方法
(2)可以访问私有成员。
这意味着特权或受保护的访问。请看下面的代码:
function Customer(orderAmount) {
    // private field
    var cost = orderAmount / 2;
    this.orderAmount = orderAmount;
    var that = this;
    // privileged method
    this.calculateProfit = function () {
        return that.orderAmount - cost;
    };
}
Customer.prototype.report = function () {
    console.log(this.calculateProfit());
};
var customer = new Customer(3000);
customer.report(); // 1500

4 公有字段
对于公有字段,原型或实例都可以使用。原型字段和方法是通过new实例共享。原型对象也是共享的。如果一个实例改变了它的对象的字段或方法,该变化并不会影响其他实例。要改变所有实例下,我们需要改变它的原型对象。
function Customer(name, orderAmount) {
    // public fields
    this.name = name;
    this.orderAmount = orderAmount;
}
Customer.prototype.type = "NORMAL";
Customer.prototype.report = function () {
    console.log(this.name);
    console.log(this.orderAmount);
    console.log(this.type);
    console.log(this.country);
};
Customer.prototype.promoteType = function () {
    this.type = "SILVER";
};
var customer1 = new Customer("Customer 1", 10);
// public field
customer1.country = "A Country";
customer1.report