创建对象并且给对象添加属性和方法
全局函数不需要加分号,但是如果是函数内部又声明了一个 函数,那么 这个函数就要加分号
工厂模式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>工厂模式</title>
<script type = "text/javascript">
/*
创建一个方法,内部创建了一个对象,根据方法传入的参数,给函数的属性赋值
函数执行后返回这个对象给调用者,这样调用者就是达到了这个对象,
好处:如果要多次创建这个类型的对象,使用这种方法,可以减少重复的显示书写创建
效率高,
缺点:因为都是通过这个方法创建的对象,所以不好区分
*/
function creat(name,age){
var box = new Object();
box.name = name;
box.age = age;
box.run = function(){
return this.name+this.age;
};
return box;
}
var a = creat("xiaoming",23);//返回一个符合要求的对象
var b = creat("xaohua",33);
alert(a.run());
alert(b.run());
</script>
</head>
<body>
</body>
</html>
构造函数
所有的构造函数都是Object
构造函数后台会new Object
没有返回语句,后台自动返回
构造函数也是函数,但是第一个字母必须大写,
必须是new 构造函数创建对象
浏览器会根据函数名首字母是不是大写,来判断是不是构造函数,只有构造函数才符合上述规则。
- 构造函数与普通函数的区别:
- 构造函数的首字母必须大写,系统会根据首字母是不是大写来判断这个
函数是不是一个构造函数 - 构造函数和普通函数一样,也可以传入参数
- 构造函数不需要返回值,因为系统会默认返回,但是普通函数
必须显示使用return 返回,否则函数没有返回值 - 构造函数用来创建对象的,使用new + 构造函数名(参数列表)
- 构造函数的首字母必须大写,系统会根据首字母是不是大写来判断这个
构造函数和工厂模式的区别
- 工厂模式可以一份代码创建多个实例,但是多个实例之间并不容易
区分他们的引用类型,因为他们的类型都是一样的 - 构造函数创建对象,不容的构造函数创建的对象是不一样的,这样
多个实例之间容易区分,但是代码书写的要比较多
- 工厂模式可以一份代码创建多个实例,但是多个实例之间并不容易
function Box(name,age){
this.name = name;
this.age = age ;
this.run = function(){
return this.name + this.age;
};
}
var a = new Box("nihao",33);
var b = new Box("haha",3);
alert(a.run());
alert(b.run());
原型
- hasOwnPropetry()
- 判断一个属性是不是对象中存在的,如果是那么返回true,如果不是返回false,false的情况可能是是原型的属性,或者不存在
function Person(){
this.name = "小明";
this.age = 33;
}
Person.prototype.gender = "男";
var a = new Person();
//判断对象a中是否存在age属性
alert(a.hasOwnProperty("age"));//对象中存在的属性true
alert(a.hasOwnProperty("gender"));//对象中不存在,原型中存在的属性false
alert(a.hasOwnProperty("ssss"));//对象和原型都不存在的属性 false
- 判断一个属性是不是对象中存在的,如果是那么返回true,如果不是返回false,false的情况可能是是原型的属性,或者不存在
- in 判断某一个属性是否存在一个对象和原型中,先查找对象中的,在查找原型中的,只要存在返回true.
function Person(){
this.name = "小明";
this.age = 33;
}
Person.prototype.gender = "男";
var a = new Person();
/*
//判断对象a中是否存在age属性
alert(a.hasOwnProperty("age"));//对象中存在的属性true
alert(a.hasOwnProperty("gender"));//对象中不存在,原型中存在的属性false
alert(a.hasOwnProperty("ssss"));//对象和原型都不存在的属性 false
*/
alert("name" in a);//true
alert("gender" in a);//true
alert("xxx" in a);//false
- 引申
- 判断一个属性是不是对象的方法
- 先用in 判断是对象或者原型的
- 再次用hasOwnProperty()判断是对象的,还是原型的。
- 判断一个属性是不是对象的方法
原型的写法
- 和构造函数相似,函数名首字母大写
- 多了原型属性和原型方法,格式:
- 构造函数名+prototype+属性名/方法名 = 初始化
实例属性和原型属性的访问规则
- 如果有实例属性优先访问实例属性
- 如果没有实例属性,那么访问原型属性
- 例子如下,访问实例属性,结果是shili,访问原型属性结果是hah
function Box(){ this.name = "shilishuxing"; };//花括号内的属性是实例属性 Box.prototype.name = "haha"; //这些事原型属性 Box.prototype.age = 23; Box.prototype.run = function(){ return "is running"; } var a = new Box(); alert(a.name);//优先访问实例属性,如果没有实例属性,那么访问原型属性
- 创建了多个原型对象,他们的原型属性和原型方法都是相同的
- 原型的属性和方法也是可以被覆盖的,如下:
function Box(){};
Box.prototype.name = "haha";
var a = new Box();
a.name = "234";
alert(a.name);
- 上面的式子结果是234,因为程序遵循就近原则
constructor
- constructor 存在于原型对象中,他指向了构造函数,
- 访问方法 Person.prototype.constructor
- 如果修改了原型中的属性constructor,那么将不在相等
function Person(){
this.age = 34;
Person.prototype.sex = "男";
}
//修改Person原型的对象字面量,不指向了Person的原型对象,那么它的属性constructor将不再是Person函数
Person.prototype ={
name:'dfsdf',
age:29,
};
var a = new Person();
alert(Person.prototype.constructor === Person);//false
Prototype 和 proto
- prototype是函数的内置属性,这个熟悉的值可以被多个对象共享
proto是对象的内置属性,这个属性指向构造函数的属性prototype
着两个prototype 和 proto是完全相同的
p.__proto__ ===Person.prototype 结果是true;
- 当一个对象访问一个他的属性的时候,会首先从自定义的属性开始查看,如果没有查找它的proto属性
function Person(){
this.age = 22;
}
Person.prototype.name="小明";
var a = new Person();
alert(a.name);
- 实例分析:
- 创建对象调用了构造函数,函数内的原型属性prototype也是一个对象,他有一个属性,name的值是xiaoming ,
- 创建了 一个对象a,那么对象的内置属性proto指向了prototype
- 当访问name属性的时候,虽然a对象没有定义,但是它的原型中有name属性,这样就可以访问到
创建对象的模式
- 组合模式:构造函数封装属性,原型封装方法
<script type="text/javascript">
//在构造方法内部封装属性
function Person(name, age) {
this.name = name;
this.age = age;
}
//在原型对象内封装方法
Person.prototype.eat = function (food) {
alert(this.name + "爱吃" + food);
}
Person.prototype.play = function (playName) {
alert(this.name + "爱玩" + playName);
}
var p1 = new Person("李四", 20);
var p2 = new Person("张三", 30);
p1.eat("苹果");
p2.eat("香蕉");
p1.play("志玲");
p2.play("凤姐");
</script>
- 动态原型模式
<script type="text/javascript">
//构造方法内部封装属性
function Person(name, age) {
//每个对象都添加自己的属性
this.name = name;
this.age = age;
/*
判断this.eat这个属性是不是function,如果不是function则证明是第一次创建对象,
则把这个funcion添加到原型中。
如果是function,则代表原型中已经有了这个方法,则不需要再添加。
perfect!完美解决了性能和代码的封装问题。
*/
if(typeof this.eat !== "function"){
Person.prototype.eat = function () {
alert(this.name + " 在吃");
}
}
}
var p1 = new Person("志玲", 40);
p1.eat();
</script>