对象创建模式

如何在ES5中实现私有成员

1
2
3
4
5
6
7
8
9
10
function Gadget(){
var name = "jonny";
this.getName = function (){
return name;
}
}

var toy = new Gadget();
console.log(toy.name); //undefined
console.log(toy.getName()); //jonny

当私有成员是一个对象时,公共方法会暴露对象引用,实例会通过引用对私有成员进行修改,从而导致私有成员的失效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function Gadget(){
var box = {
x:10,
y:10
}
this.getBox = function (){
return box;
}
}

var toy = new Gadget();
console.log(toy.box); //undefined
console.log(toy.getBox()); //返回{x:10,y:10}
let box = toy.getBox();
box.x = 20;
console.log(toy.getBox());//{x:20,y:10}

原型模式

为了节省开支与避免重复复制相同的成员与方法,一般会把常用的成员与方法放进原型中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function Xbox(){
var name = "Mic";
this.getName = function (){
return name;
}
}

Xbox.prototype = (function (){
var browser = 'webKit';
return {
getBrowser:function (){
return browser;
}
}
}())

var toy = new Xbox();
toy.getName(); //mic
toy.getBrowser(); //webkit

揭示模块模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var module;

(function (){
var color = 0xff0000;
var position = {
x:0,
y:0
}
var size = {
w:100,
h:100
}
var rectAngle = function (){
return {
x:position.x,
y:position.y,
w:position.x + size.w,
h:position.y + size.h
}
}
module = {
color:color,
position:position,
size:size,
rectAngle:rectAngle
}
})()

闭包实现私有静态方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var Uid = (function (){
var count = 0;
var newUid = function (){
count+=1;
};
newUid.prototype.getUid = function (){
return count;
}
return newUid;
})()

var a = new Uid();
a.getUid();// 1
var b = new Uid();
b.getUid();// 2

ES5常量实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
var constant = (function (){
var constants = {},
ownProp = Object.prototype.hasOwnProperty,
allowed = {
string:1,
number:1,
boolean:1
},
prefix = (Math.random() + '_').slice(2);
return {
set:function (name,value){
if(this.isDefined(name)){
return false;
}
if(!ownProp.call(allowed,typeof value)){
return false;
}
constants[prefix + name] = value;
return true;
},
get:function (name){
if(this.isDefined(name)){
return constants[orefix + name];
}else{
return null;
}
},
isDefined:function (name){
return ownProp.call(constants,prefix + name);
}
}
})()