一、生成实例对象的原始模式
var Cat = {
name : '',
color : ''
}
var cat1 = {}; // 创建一个空对象
cat1.name = "大毛"; // 按照原型对象的属性赋值
cat1.color = "黄色";
二、工厂模式
function creatObject(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function () {
alert (this.name);
}
return o;
}
三、构造函数模式
- 所谓"构造函数",其实就是一个普通函数,但是内部使用了this变量。对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。
function Cat(name,color){
this.name=name;
this.color=color;
}
var cat1 = new Cat("大毛","黄色");
var cat2 = new Cat("二毛","黑色");
alert(cat1.name); // 大毛
alert(cat1.color); // 黄色
要创建Cat的新实例,必须使用new操作符,系统内部创建过程如下:
- 创建一个新对象
- 将构造函数的作用域赋给新对象(因此this就指向了这个新对象)
- 执行构造函数中的代码(为这个新对象添加属性和方法)
- 返回新对象
构造函数和普通函数的唯一区别在于调用方式不同,构造函数也是普通函数,任何通过new调用的函数都可以是构造函数。通常在项目中为了区分,我们都将构造函数的第一个字母大写 以区别于普通函数
2.构造函数的问题
使用构造函数的时候,每个方法都要在每个实例上重新创建一遍,然而创建两个完全同样任务的Function实例是没有必要的,造成内存的浪费
四、原型模式( Prototype模式)
Javascript规定,每一个函数都有一个prototype(原型)属性,它是一个指针,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承和共享。
function Cat(name,color){
this.name = name;
this.color = color;
}
Cat.prototype.type = "猫科动物";
Cat.prototype.eat = function(){alert("吃老鼠")};
// 实例
var cat1 = new Cat("大毛","黄色");
var cat2 = new Cat("二毛","黑色");
alert(cat1.type); // 猫科动物
cat1.eat(); // 吃老鼠
//验证是同一块内存
alert(cat1.eat == cat2.eat); //true
这时所有实例的type属性和eat()方法,其实都是同一个内存地址,指向prototype对象,因此就提高了运行效率。
- 理解原型对象
只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象,而每个远行对象都会自动获得一个constructor(构造函数)属性,这个属性包含一个指向prototype属性所在函数的指针。 原型是动态的,随时修改 随时生效
不论是对象的还是构造函数本身的prototype指向的是本身引用类型的父引用类型的对象实例
constructor指向自身prototype原型对象的构造函数
- 原型对象的问题
首先,他省略了为构造函数传递初始化参数这一环节,结果所有实例在默认情况下都将取得相同的属性值。
重要的是,由于原型对象是共享的,原型中的属性是被很多实例共享的,通过某个实例修改原型中的属性,其他的实例的属性值也会被修改。
五、组合使用构造函数和原型模式
就是属性在本身的构造函数中实现,而方法在prototype原型中实现。