1、工厂模式,解决了创建多个相似对象的问题,但是没有解决对象识别的问题。
function creatPerson(name, age) { var obj = new Object(); obj.name = name; obj.age = age; obj.sayHello = function() { document.write(obj.name + " 的年龄是: " + obj.age); } return obj; } creatPerson("zhangsan", 11).sayHello()2、构造函数模式
function Person(name, age) { this.name = name; this.age = age; this.sayHello = function() { document.write(this.name + " 的年龄是: " + this.age); document.write("<br>"); } } var p1 = new Person("zhangsan", 11); console.log("p1 :",p1); console.log("p1 instanceof Object :",p1 instanceof Object); console.log("p1 instanceof Person: :",p1 instanceof Person); p1.sayHello(); document.write("p1 instanceof Object: "+ p1 instanceof Object); document.write("<br>"); document.write("p1 instanceof Person: "+p1 instanceof Person); document.write("<br>");当使用new创建一个对象要经过以下过程。
- 创建一个新的对象
- 将构造函数的作用域赋值给新对象(this指向了新对象)
- 执行构造函数中的代码
- 返回新对象
构造函数与其他函数的唯一区别,就在于调用他们的方式不同。任何函数只要通过new操作符来调用,那他 就是构造函数
所有的对象均继承自Object对象。
通过call方法修改函数的作用域
var obj = new Object(); Person.call(obj, "obj",12) obj.sayHello();
3、原型模式
由于在原型中的查找是一次搜索,因此对原型的每一次修改能够立刻体现在实例上。但如果重新写整个原型就不行了,因为实例的prototype属性指向原型,但是修改后的原型找不到了。
5、动态原型模式eg.
- 我们创建的每一个函数都有一个prototype属性,这个属性为一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型所有实例共享的属性和方法。这个对象会自动获得一个constructor的属性,这个属性为指向prototype属性所在函数的指针。
- 当调用构造函数创建一个新的实例之后,该实例的内部有一个指向构造函数prototype对象的指针。
- isPrototypeOf 方法用来实例对象的prototype属性是否指向构造函数的prototype对象;Object.getPrototypeOf方法用来获取实例的prototype对象
document.write("Person.prototype.isPrototypeOf(p1) :"+Person.prototype.isPrototypeOf(p1)); //true document.write("<br>") document.write("Object.prototype.isPrototypeOf(p1) :"+Object.prototype.isPrototypeOf(p1));//true document.write("<br>") console.log("Object.getPrototypeOf(p1): ",Object.getPrototypeOf(p1));
- 虽然通过实例对象可以访问原型中的值,但却不能修改原型中的值,如果通过实例修改原型中的值实际是实例中多了一个和原型中一样的属性,实例中的值覆盖了原型中的值。hasOwnProperty方法用来检测实例中是否有某个属性。
function Person() { }; function Teacher(){ this.name = "teacher"; } Person.prototype.name = "zhang"; Person.prototype.age = 11; var t1 = new Teacher(); var p1 = new Person(); var p2 = new Person(); p1.name = "lee"; console.log("p1: ", p1); console.log("p1.name: ", p1.name); console.log("p1: ", p2); console.log("t1.hasOwnProperty name :", t1.hasOwnProperty("name")); console.log("p1.hasOwnProperty name :", p1.hasOwnProperty("name")); console.log("p2.hasOwnProperty name :", p2.hasOwnProperty("name")); console.log("name in p1 :", "name" in p1); console.log("name in p2 :", "name" in p2); delete p1.name; console.log(" delete p1.name"); console.log("p1: ", p1); console.log("p1.name: ", p1.name);
- 原型与in 操作符。in操作符会在通过对象能够访问到给定属性时返回true
- Object.keys得到实例中所有课遍历的字符串数组,Object.getOwnPrototypeNames得到所有实例属性无论是否可枚举。
console.log("Object.keys(p1): ", Object.keys(p1)); console.log("Object.getOwnPrototypeNames(Person.prototype): ", Object.getOwnPropertyNames(Person.prototype));
由于在原型中的查找是一次搜索,因此对原型的每一次修改能够立刻体现在实例上。但如果重新写整个原型就不行了,因为实例的prototype属性指向原型,但是修改后的原型找不到了。
var p1 = new Person(); Person.prototype.tel = 18635581189; document.write("p1.tel: " + p1.tel); Person.prototype = {tian:"234"} document.write("<br>"); document.write("p1.tian: " + p1.tian); document.write("<br>"); var p2 = new Person(); document.write("p2.tian: " + p2.tian); document.write("<br>");
- 问题,对于引用类型有问题。eg.
Person.prototype.arras = ["1"]; var p1 = new Person(); p1.arras.push("p2") var p2 = new Person(); document.write(" 的年龄是: " + p2.arras); document.write("<br>");
function Person(name, age) { this.name = name; this.age = age; }; Person.prototype Person.prototype = { sayHello : function() { document.write(this.name + " 的年龄是: " + this.age) } } Object.defineProperty(Person.prototype, "constructor", { enumerable : false, value : Person }); new Person("zhang",19).sayHello();
5、动态原型模式eg.
function Person(name, age) { this.name = name; this.age = age; if (typeof this.sayHello != "function") { Person.prototype.sayHello = function() { document.write(this.name + " 的年龄是: " + this.age) } } }; new Person("zhang", 19).sayHello();
6、寄生构造函数模式,这种模式下返回的值和构造函数的原型没有关系。
function Person(name, age) { var o = new Object(); o.name = name; o.age = age; o.sayHello = function(){ document.write(o.name + " 的年龄是: " + o.age); } return o; }; var p1 =new Person("zhang", 20); p1.sayHello();
构造函数在不返回值的情况下,默认返回对象的实例。而通过return 可以重写调用构造函数时的返回值。