创建对象的三种方式
1. 使用系统的构造函数创建对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
//练习:有一个黄色的小狗,叫大黄,今年已经三岁了,250斤的重量每次走路都很慢,喜欢吃大骨头
var dog=new Object();
dog.color="yellow";
dog.name="大黄";
dog.age=3;
dog.weight="250斤";
dog.run=function (){
console.log("很慢")
};
dog.eat=function (){
console.log("喜欢吃大骨头");
}
console.log(dog.color);
console.log(dog.name);
console.log(dog.age);
console.log(dog.weight);
dog.run();
dog.eat();
//dog2
var dog2=new Object();
dog2.color="black";
dog2.name="小黑";
dog2.age=1;
dog2.weight="100斤";
dog2.run=function (){
console.log("很快")
};
dog2.eat=function (){
console.log("喜欢吃小骨头");
}
console.log(dog.color);
console.log(dog.name);
console.log(dog.age);
console.log(dog.weight);
dog.run();
dog.eat();
练习:创建一个手机对象,手机有型号,有颜色,可以打电话和发短信
var mobile=new Object();
mobile.type="ios";
mobile.color="white";
mobile.call=function (num){
console.log("拨打电话"+num+"颜色"+this.color);
};
mobile.send=function (num){
console.log("已向"+num+"发送短信")
}
console.log(mobile.type);
console.log(mobile.color);
mobile.call(123123132);
mobile.send(2321231);
//判断一个变量(对象)是不是属于某个类型的
//instanceof
console.log(dog instanceof Object)
</script>
</body>
</html>
当想要创建多个相似的对象比如dog3、dog4、dog5…,如果仅仅如上所写,那必然会有很多累赘的代码,这个时候函数就可以派上用场。
工厂模式创建对象:
//工厂模式创建对象
//创建新对象、添加对象属性、返回对象的过程放到这个函数中,用户只需调用函数来生成对象而无需关注对象创建细节,这叫工厂模式
function createPerson(name,age){
var obj=new Object();
obj.name=name;
obj.age=age;
obj.sayHi=function (){
console.log(this.name+"今年"+this.age);
}
return obj;
}
var per1=createPerson("zhangsan",11);
var per2=createPerson("lisi",18);
per1.sayHi();
per2.sayHi();
//判断一个变量(对象)是不是属于某个类型的
//instanceof
console.log(per1 instanceof Object)
console.log(per2 instanceof Object)
使用工厂模式创建对象可以解决代码重复的问题,但是无法识别对象类型。比如我想知道创建的per1是否是person类型。无法判断。此时就需要用到定义的构造函数。
2. 使用自定义的构造函数创建对象
js 中函数和构造函数的区别:
- 构造函数名首字母大写,函数首字母小写
- 构造函数 使用new 操作符来调用,函数不需要。
//函数和构造函数的区块(函数首字母是否大写)
function Person(name,age){
this.name=name;
this.age=age;
this.sayHi=function(){
console.log(this.name+" 今年 "+ this.age)
},
this.sayHello=function(){
console.log("hello");
},
}
var per1 =new Person("张三",18);
var per2 =new Person("李四",20);
per1.sayHi();
per2.sayHi();
console.log(per1 instanceof Person)//true
console.log(per2.constructor === Person)//true
console.log(per1.sayHello=== per2.sayHello) //false
自定义构造函数创建对象 做了以下几件事:
- 1.在内存中开辟空间(申请一块空闲的空间),存储新创建的对象
- 2.把this设置为当前对象
- 3.设置当前对象的属性和方法
- 4.返回 this–当前对象–return this(正常省略)
此时通过构造函数创建的对象都有一个constructor属性,它是一个指向构造函数本身的指针,因此就可以检测对象的类型。
但是这个时候,两个对象的同名函数sayHello是不相等的,这就意味着,两个同名函数的内存空间是不一样的,也就是构造函数的方法在实例化对象的时候都会重新创建一次,进而占用不必要的内存。此时就需要用到原型模式。
原型模式创建对象:
每个构造函数都有个prototype属性,这个属性是一个指针,指向原型对象。而这个原型对象包含了这个构造函数所有实例可共享的属性和方法。而实例对象中也有个proto属性,也是指向原型对象。这样原型对象=构造函数.prototype=实例对象.proto。这样实例对象就可以访问到原型对象的所有属性和方法。
这样把需要共享的属性和方法都放到原型对象中去,这样每次实例化一个对象的时候,就不会重新创建想要的属性和方法,从而减少内存的使用。
//原型模式创建对象
function Person(){
};
Person.prototype={
constructor:Person,
skin:"yellow",
show:function(){
console.log("happy everyday");
}
}
var per3=new Person();
console.log(per3.skin);
per3.show();
构造函数+原型模式创建对象:
构造函数定义实例对象独有的属性,而原型模式定义共享的属性和方法。这样每个实例对象既有自己的独特性,也有共享的属性和方法。
function Person(name,age){
this.name=name;
this.age=age;
};
Person.prototype={
constructor:Person,
skin:"yellow",
show:function(){
console.log("happy everyday");
}
}
var per3=new Person("呜呜",18);
console.log(per3.skin);
console.log(per3.name);
per3.show();
3. 字面量的方式创建对象
//字面量的方式创建对象
var obj={};
//添加属性
obj.name="张三";
obj.age=18;
//添加方法
obj.say=function(){
console.log("我叫"+this.name);
}
obj.say();
//优化
var obj1={
name:"李四",
age:20,
say:function(){
console.log("我叫"+this.name);
}
}
obj1.say();
字面量的方式创建的是一次性的对象,比如想再创建一个叫赵六的,只能再var 一个obj。
因此最佳使用还是自定义构造函数+原型模式。