1创建对象
工厂模式
function createPerson(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function() {
alert(this.name);
};
return o;
}
var person1 = createPerson("yip", 30, "software");
person1.sayName();
console.info(person1.age);
构造函数模式
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() {
alert(this.name);
};
}
var person2 = new Person("yip1", 29, "soft");
``
//构造函数属性
console.info(person2.constructor === Person); //ture
//检测对象的类型
console.info(person2 instanceof Object); //true
console.info(person2 instanceof Person); //true
//作为普通函数使用
Person("yip2", 28, "software");
window.sayName(); //yip2
//在另一个作用域调用
var o1 = new Object();
Person.call(o1, "yip3", 28, "software");
o1.sayName(); //yip3
使用构造函数的主要问题,就是每个方法都要在每个实例上重新创建一遍
原型模式
function Person2() {}
Person2.prototype.name = "yip3";
Person2.prototype.age = "30";
Person2.prototype.job = "software";
Person2.prototype.sayName = function() {
alert(this.name);
};
var person3 = new Person2();
person3.sayName(); //yip3
var person4 = new Person2();
person4.sayName(); //yip3
alert(person3.sayName() == person4.sayName()); //true
//isPrototypeOf()方法 确定对象间是否存在这中关系
console.info(Person2.prototype.isPrototypeOf(person3));
//getPrototypeof()方法 返回对象的原型
console.info(Object.getPrototypeOf(person3) === Person2.prototype); //true
//屏蔽了原型对象的同名属性。阻止访问原型中的那个属性
person3.name = "ooo";
person3.sayName(); //ooo
delete 删除实例属性
delete person3.name;
person3.sayName(); //yip3
hasOwnProperty 检测一个属性是存在于实例中,还是存在于原型中
console.info(person3.hasOwnProperty("name")); //false
原型于in操作符
console.info("name" in person3); //true 无论属性存在于原型还是实例都是返回true
//原型属性返回true 存在于实例的属性返回false
function hasPrototypePro(object, pro) {
return !object.hasOwnProperty(pro) && pro in object;
}
Object.keys() 枚举素有属性,返回一个可枚举的字符串数组(constructor不可枚举)
console.info(
Object.keys(Person2.prototype)); //name age job sayName
Object.getOwnPropertyNames() 返回所有属性,包括constructor
console.info(Object.getOwnPropertyNames(Person2.prototype)); //constructor name age job sayName
重写了默认的prototype对象,per2实例的constructor属性指向了Object
function Person4() {}
var per1 = new Person4();
Person4.prototype = {
name: "yip4",
age: 28,
job: "software",
sayName: function() {
alert(this.name);
}
};
var per2 = new Person4();
//console.info(per1.sayName()); //error 重写原型切断了现有原型与之前已经存在的对象实例之间的联系,他们引用的仍然是最初的原型
console.info(per2.constructor == Object); //true
console.info(per2.constructor == Person4); //false
组合使用构造函数模式和原型模式
原型对象的引用类型的属性没办法通过实例化对象添加同名属性隐藏对应的同名属性,基础类型的属性可以,所以才需要这种模式
function Person5(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.frends = [1, 2];
}
Person5.prototype = {
constructor: Person5,
sayName: function() {
alert(this.name);
}
};
var pers1 = new Person5("yip", 25, "sof");
var pers2 = new Person5("yip1", 20, "egg");
pers1.frends.push(3);
console.info(pers1.frends); // [1, 2, 3]
console.info(pers2.frends); // [1, 2]
动态原型模式
function Person6(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
if (typeof this.sayName != "function") {
Person6.prototype.sayName = function() {
alert(this.name);
};
}
}
寄生构造函数模式
function SpecialArray() {
//创建数组
var array = new Array();
//添加值 arguments获取的是实参,不是形参,所以SpecialArray()并没有形参接收传递过来的参数
array.push.apply(array, arguments);
array.toPipedString = function() {
return this.join("|");
};
return array;
}
var colors = new SpecialArray("red", "blue", "black");
alert(colors.toPipedString()); //输出:red|blue|black
与工厂模式的区别:
1、寄生模式创建对象时使用了New关键字
2、寄生模式的外部包装函数是一个构造函数
除了上面这2个区别寄生模式和工厂模式几乎一样, 构造函数在不返回值的情况下,默认返回对象的新实例。而通过在构造函数的末尾添加一个return 语句, 可以重写调用构造函数是返回的值
稳妥构造函数模式
function Person6(name, age) {
//创建要返回的对象
var o = new Object();
//可以在这里定义私有变量和函数
//添加方法
o.sayName = function() {
alert(name);
};
//返回对象
return o;
}
var person = Person6("张三", 22);
person.sayName(); //使用稳妥构造函数模式只能通过其构造函数内部的方法来获取里面的属性值
2继承
原型链
借用构造函数
function SuperType() {
this.colors = ["red", "blue", "green"];
}
function SubType() {
SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("black");
console.info(instance1.colors); //["red", "blue", "green", "black"]
var instance2 = new SubType();
console.info(instance2.colors); // ["red", "blue", "green"]
组合继承(伪经典继承)
使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例的继承
function SuperType1(name) {
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType1.prototype.sayName = function() {
alert(this.name);
};
function SubType1(name, age) {
//继承属性
SuperType1.call(this, name);
this.age = age;
}
//继承方法
SubType1.prototype = new SuperType1();
SubType1.prototype.constructor = SubType1;
SubType1.prototype.sayAge = function() {
alert(this.age);
};
var instance = new SubType1("yip", 25);
instance.colors.push("black");
console.info(instance.colors); //["red", "blue", "green", "black"]
instance.sayName(); //yip
instance.sayAge(); //25
var instance2 = new SubType1("yip222", 24);
console.info(instance2.colors); //["red", "blue", "green"]
instance2.sayName(); //yip
instance2.sayAge(); //25
console.info(SubType1.prototype.colors);
原型式继承
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
var person = {
name: "yip",
friends: ["shelly", "court", "van"]
};
var anotherPerson = object(person);
anotherPerson.friends.push("a");
var bnotherPerson = object(person);
bnotherPerson.friends.push("b");
console.info(person.friends); //["shelly", "court", "van","a", "b"]
//Object.create() 接收两个参数,一个用作新对象原型的对象一个新对象定义额外属性对象
var cnotherPerson = Object.create(person, {
name: { value: "yip2" }
});
console.info(cnotherPerson.name); //yip2
寄生式继承
function createAnother(origin) {
var clone = object(origin);
clone.sayHi = function() {
alert("hi");
};
return clone;
}
var dnotherPerson = createAnother(person);
dnotherPerson.sayHi();
寄生组合式继承
function inheritPrototype(subType, superType) {
var prototype = Object.create(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
function SuperType(name) {
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function() {
alert(this.name);
};
function SubType(name, age) {
SuperType.call(this, name);
this.age = age;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function() {
alert(this.age);
};