面向对象编程

面向对象

面向对象 MDN

JavaScript面向对象编程

命名空间

如果你在公司 var a = 1;是要被离职的

因为你不知道 a以前是什么

1
2
3
4
5
6
7
8
// 全局命名空间
var MYAPP = MYAPP || {};
//等价于
if(MYAPP){
var MYAPP = MYAPP
}else{
var MYAPP = {}
}

代码技巧 先看看表达式的值是什么

1
2
3
4
5
6

1 || 2 //1

1 && 2 && 3 //3

0||null||undefined||1 //1

重要概念

1
2
3
4
5
6
7
8
a || b 

c && d

//它们的值基本不可能是 true / false
//五个falsy值

// 0 NaN '' null undefined
1
2
3
4
5
6
7
8
9
10
11
12
1 && 0  // 0

1 && 0 && 2 // 0

1 && 0 && console.log(3) //打印3不会执行 会返回 0

1 && 2 && 3 // 3


0 || undefined || null || 1 // 1

0 || undefined || null || 1 || 0 || null // 1

回到之前的命名空间写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var app = {}//危险代码

if(app){
//app = app 这句可以不写 是废话
}
}else{
app = {}
}

// 安全写法

var app2 = app2 || {}

if(app2){
app2 = app2
}else{
app2 = {}
}

this复习

待更新。。。。

new是做啥的

当我们需要100个士兵 就要写100次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var 士兵们 = [];
var 士兵 ;
for(var i=0;i<100;i++){
士兵 = {
ID: i, // 用于区分每个士兵
兵种:"美国大兵",
攻击力:5,
生命值:42,
行走:function(){ /*走俩步的代码*/},
奔跑:function(){ /*狂奔的代码*/ },
死亡:function(){ /*Go die*/ },
攻击:function(){ /*糊他熊脸*/ },
防御:function(){ /*护脸*/ }
}
士兵们.push(士兵)
}

这样是很耗内存的因为 每个士兵自己都有 这些方法 但这些方法内容是一样的 就会出现500个方法

1
2
3
4
5
行走:function(){ /*走俩步的代码*/},
奔跑:function(){ /*狂奔的代码*/ },
死亡:function(){ /*Go die*/ },
攻击:function(){ /*糊他熊脸*/ },
防御:function(){ /*护脸*/ }

士兵共有属性

proto__ __ 这样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var 士兵共有属性 = {
兵种:"美国大兵",
攻击力:5,
行走:function(){ /*走俩步的代码*/},
奔跑:function(){ /*狂奔的代码*/ },
死亡:function(){ /*Go die*/ },
攻击:function(){ /*糊他熊脸*/ },
防御:function(){ /*护脸*/ }
}

var 士兵们 = [];
var 士兵 ;
for(var i=0;i<100;i++){
士兵 = {
ID: i, // 用于区分每个士兵
生命值:42
}
/*实际工作中不要这样写__proto__ 不是标准属性*/

士兵.__proto__ = 士兵共有属性

士兵们.push(士兵)
}

这样你会感觉士兵和 士兵共有属性很松散

使用函数把 士兵 和 士兵共有属性 包裹起来

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
var 士兵共有属性 = {
兵种:"美国大兵",
攻击力:5,
行走:function(){ /*走俩步的代码*/},
奔跑:function(){ /*狂奔的代码*/ },
死亡:function(){ /*Go die*/ },
攻击:function(){ /*糊他熊脸*/ },
防御:function(){ /*护脸*/ }
}

function create士兵(id){
var 士兵 = {
ID:i,//
生命值:42
}

士兵.__proto__ = 士兵共有属性

return 士兵
}


//创建士兵
var 士兵们 = [];
var 士兵 ;
for(var i=0;i<100;i++){
士兵们.push( create士兵(i) )
}

这样 create士兵 和 士兵共有属性还是没太大关联性

把 “士兵的共有属性” 放到 “create士兵” 的属性 里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function create士兵(id){
var 士兵 = {
ID:i,//
生命值:42
}

士兵.__proto__ = create士兵.士兵共有属性

return 士兵
}

create士兵.士兵共有属性 = {
兵种:"美国大兵",
攻击力:5,
行走:function(){ /*走俩步的代码*/},
奔跑:function(){ /*狂奔的代码*/ },
死亡:function(){ /*Go die*/ },
攻击:function(){ /*糊他熊脸*/ },
防御:function(){ /*护脸*/ }
}

JS之父的关怀

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
function 士兵(id){
//step1
//var temp = {}
//step2
//this = temp
//step3
//this.__proto__ = create士兵.prototype
this.ID = id;
this.生命值 = 42
//step4
//return this
}

士兵.prototype = {
constructor:士兵,
兵种:"美国大兵",
攻击力:5,
行走:function(){ /*走俩步的代码*/},
奔跑:function(){ /*狂奔的代码*/ },
死亡:function(){ /*Go die*/ },
攻击:function(){ /*糊他熊脸*/ },
防御:function(){ /*护脸*/ }
}

// 你要做的事情 就是 加个new

var 士兵 = new 士兵(id);

原理 new 士兵()之后

  1. 生成一个临时对象 temp
  2. 然后用 this指向 这个临时对象 temp
  3. 然后让this的原型 等于这个函数的prototype
  4. 而且也不用return 这个事 也帮你做了 帮你返回this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var obj =new Object()

自有属性 空
obj.__proto__ === Object.prototype

var array = new Array('a','b','c')
自有属性 0:'a' 1:'b' 2:'c' length:3
array.__proto__ === Array.prototype
Array.prototype.__proto__ === Object.prototype

var fn =new Function('x','y','return x+y')
自有属性 length:2 不可见函数体: 'return x+y'
fn.__proto__ === Function.prototype


Array is a Function
Array = function(){...}
Array.__proto__ === Function.prototype