JavaScript 对象的全部属性都是公有的,没有显式的方法指定某个属性不能被外界访问。安全
模块模式是一种用于建立拥有私有数据的单件对象的模式。 基本作法是使用当即调用函数表达式(IIFE)来返回一个对象。原理是利用闭包。闭包
var yourObj = (function(){
// private data variables
return {
// public methods and properties
}
}());
复制代码
模块模式还有一个变种叫暴露模块模式,它将全部的变量和方法都放在 IIFE
的头部,而后将它们设置到须要被返回的对象上。ide
// 通常写法
var yourObj = (function(){
var age = 25;
return {
name: "Ljc",
getAge: function(){
return age;
}
}
}());
// 暴露模块模式
var yourObj = (function(){
var age = 25;
function getAge(){
return age;
};
return {
name: "Ljc",
getAge: getAge
}
}());
复制代码
模块模式在定义单个对象的私有属性十分有效,但对于那些一样须要私有属性的自定义类型呢?你能够在构造函数中使用相似的模式来建立每一个实例的私有数据。函数
function Person(name){
// define a variable only accessible inside of the Person constructor
var age = 22;
this.name = name;
this.getAge = function(){
return age;
};
this.growOlder = function(){
age++;
}
}
var person = new Person("Ljc");
console.log(person.age); // undefined
person.age = 100;
console.log(person.getAge()); // 22
person.growOlder();
console.log(person.getAge()); // 23
复制代码
这里有个问题:若是你须要对象实例拥有私有数据,就不能将相应方法放在 prototype
上。ui
若是你须要全部实例共享私有数据。则可结合模块模式和构造函数,以下:this
var Person = (function(){
var age = 22;
function InnerPerson(name){
this.name = name;
}
InnerPerson.prototype.getAge = function(){
return age;
}
InnerPerson.prototype.growOlder = function(){
age++;
};
return InnerPerson;
}());
var person1 = new Person("Nicholash");
var person2 = new Person("Greg");
console.log(person1.name); // "Nicholash"
console.log(person1.getAge()); // 22
console.log(person2.name); // "Greg"
console.log(person2.getAge()); // 22
person1.growOlder();
console.log(person1.getAge()); // 23
console.log(person2.getAge()); // 23
复制代码
这是一种伪继承。一个对象在不改变原型对象链的状况下获得了另一个对象的属性被称为“混入”。所以,和继承不一样,混入让你在建立对象后没法检查属性来源。 纯函数实现:spa
function mixin(receiver, supplier){
for(var property in supplier){
if(supplier.hasOwnProperty(property)){
receiver[property] = supplier[property];
}
}
}
复制代码
这是浅拷贝,若是属性的值是一个引用,那么二者将指向同一个对象。prototype
构造函数也是函数,因此不用 new 也能调用它们来改变 this
的值。设计
在非严格模式下, this
被强制指向全局对象。code
而在严格模式下,构造函数会抛出一个错误(由于严格模式下没有为全局对象设置 this
,this
保持为 undefined
)。
而不少内建构造函数,例如 Array
、RegExp
不须要 new
也能正常工做,这是由于它们被设计为做用域安全的构造函数。
当用 new
调用一个函数时,this
指向的新建立的对象是属于该构造函数所表明的自定义类型。所以,可在函数内用 instanceof
检查本身是否被 new
调用。
function Person(name){
if(this instanceof Person){
// called with "new"
}else{
// called without "new"
}
}
复制代码
具体案例:
function Person(name){
if(this instanceof Person){
this.name = name;
}else{
return new Person(name);
}
}
复制代码