一 对象字面量

对象字面量就是一个 {},里面的属性和方法均是 key : value 键值对。

1
2
3
4
5
6
7
8
let teacher = {
name:'扶桑',
age:27,
school:'神木中学',
teach:function(){
console.log(this.name +'教语文')
}
}

二 工厂模式

上面创建对象的方式是单个单个的,当要创建很多和上面有相同特征对象时,繁琐又耗时间。
这时使用工厂模式大批量地创建对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function Teacher(name,age,course){
var teacher = {
name,
age,
school: '太阳中学',
teach:function(){
console.log(this.name +'教'+course);
}
}
return teacher;
}

let fuSang = Teacher('扶桑',27,'语文');
console.log(fuSang); // {name: "扶桑", age: 27, school: "神木中学", teach: ƒ}
let shenMu = Teacher('神木',26,'历史'); // 可快速创建另一个对象
console.log(shenMu.teach()) // 神木教历史,undefined

控制台打印效果:

三 构造函数创建对象

Object()是浏览器自带的函数对象

1
var teacher1 = new Object();
1
2
3
4
5
6
7
8
9
10
11
12
// 自定义构造函数
function Teacher(name,age,course){
this.name = name;
this.age = age;
this.teach = function(){
console.log(this.name +'教'+course);
}
console.log(this);
}

Teacher('扶桑',27,'语文');
console.log(name); // 扶桑

Teacher(‘扶桑’,27,’语文’); 只是普通函数的调用,调用Teacher() 打印 this 的结果是 window 对象。即 this 指向的是 window 对象,并声明了全局的 name、age 变量和 teach 函数,如下图:

使用 new 创建一个新的对象,将函数内部的 this指向新的对象。构造函数中没有返回值。

1
2
let shenMu = new Teacher('神木',26,'历史'); 
// this指向新对象 shenMu,打印 this是一个 Teacher对象,指向新对象 shenMu
1
2
3
4
5
6
7
8
9
10
11
/*
Teacher{
age: 26
name: "神木"
teach: ƒ ()
__proto__:
-constructor: ƒ Teacher(name,age,course) // 用的构造函数 Teacher()创建的对象
__proto__: Object}
*/
console.log(name); // 扶桑
console.log(shenMu.name); // 神木

使用构造函数创建对象一般不像上面 Teacher() 那样大批量创建对象,而是会用到原型对象,把构造函数里面的行为封装起来并给到 prototype属性,这样在大量创建对象后减少堆内存占用,下面举例说明:

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// 定义构造函数
function Dog(name,color,game){
this.name = name;
this.color = color;
this.playGame = function(){
console.log(this.color + '的' + this.name + '喜欢' + game)
}
}

var dogXiaobai = new Dog('小白','白色的','追蝴蝶');
var dogXiaohei = new Dog('小黑','黑色的','打架');
console.log(dogXiaobai.playGame == dogXiaohei.playGame); // false
/*
上面两个对象的 playGame是不等的,但是两个对象里面的 playGame函数内容是一样的,每创建一个 Dog对象,堆内存中就多一个 function playGame(){}
所以想办法让每个对象中的属性是函数的都指向同一个地址,如下
*/
var playGame1 = function(){ // 函数是对象,对象是引用的类型,放置的内存地址给到 playGame1
console.log(this.color + '的' + this.name + '喜欢' + game)
}
function Dog1(name,color,game){
this.name = name;
this.color = color;
this.playGame = playGame1 // 这里即是把内存地址给 this.playGame,每创建一个 Dog1对象都共用 playGame1函数
}
var dogHuahua = new Dog1('花花','黄色、白色的','黏主人');
var dogHuaihui = new Dog1('灰灰','灰色的','吃大黄的饭');
console.log(dogHuahua.playGame == dogHuaihui.playGame); // true,两个对象的 playGame属性相等,占据的空间减少了

// 一般对象有很多行为,每个行为都像 playGame1 这样单独拎出来声明很不方便,不建议这样使用
// 而是将一个类都需要用到的方法封装到一个对象上,并将此对象给到构造函数的 prototype属性,这样用此类创建的每个对象都会有这些行为
function Dog2(name,color,game,food){
this.name = name;
this.color = color;
this.game = game;
this.food = food
}
var dogProto = {
playGame(){
console.log(this.color + '的' + this.name + '喜欢' + this.game)
},
eat(){
console.log(this.name + '爱吃' + this.food)
},
sleep(){
console.log('小狗们都爱睡!')
}
}
Dog2.prototype = dogProto;
var dogHuahua = new Dog2('花花','黄色、白色的','黏主人','火腿肠');
var dogDoudou = new Dog2('豆豆','浅白色的','出去玩','狗粮');
console.log(dogHuahua.eat()); // 花花爱吃火腿肠
console.log(dogDoudou.eat()); // 豆豆爱吃狗粮

四 类 class 关键字创建对象(es6)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Teacher{
constructor(name,age,course){
this.name = name;
this.age = age;
this.teach = function(){
console.log(this.name +'教'+course);
}
}
}
var fuSang = new Teacher('扶桑',27,'语文');
// 类创建出来的对象与构造函数创建的基本一样
console.log(fuSang);
/*Teacher {name: "扶桑", age: 27, teach: ƒ}
age: 27
name: "扶桑"
teach: ƒ ()
__proto__:
constructor: class Teacher // 区别在这里显示构造器是类 class,构造函数构造器则是函数 f=
__proto__: Object
// */

若对原型对象不熟悉,可以跳转下面的地址学习。

https://www.runoob.com/js/js-object-prototype.html