对象创建方法:
- 工厂方法
- 构造函数模式
- 原型模式
- 组合构造函数和原型模式
- 寄生构造函数模式
- 问题构造函数模式
工厂模式:
function Person(name, age){ var obj = new Object(); //创建对象 obj.name = name; //添加方法、属性 obj.age = age; obj.sayName = function(){ alert(this.name); } return obj; //返回对象 }var people = Person("yangxunwu", 24);
缺点:返回的对象全部是object的实例,无法完成对象识别
构造函数模式:
function Person(name, age){ this.name = name; //添加方法、属性 this.age = age; this.sayName = function(){ alert(this.name); }; } var people = new Person("yangxunwu", 24);//注意多了new操作
构造函数创建实例时,必须用new操作符,经历四个步骤:
- 创建对象
- 将构造函数的作用域赋给对象。(this指向新对象)
- 执行构造函数代码。
- 返回新对象。
缺点:虽然创建的实例可以通过instanceof操作符 来识别,但函数无法复用。
原型模式:
function Person(){ //创建空的构造函数 } Person.prototype.age = age; //构造函数原型上添加属性和方法,达到函数复用 Person.prototype.sayName = function(){ alert(Person.prototype.name); }; var people = new Person();
当创建一个新函数时,会自动根据特定规则为函数创建prototype属性,这个属性是一个指针指向函数的原型对象,
原型对象会自动的获得一个constructor属性,这也是一个指针,指向拥有这个prototype属性的函数。
Pesson.prototype.constructor = Person
创建自定义构造函数后,其原型对象自动获得constructor属性,其他的方法都从object继承。当通过构造函数创建
一个新实例后,实例自动获得一个指针,指向构造函数的原型对象,一般名称是__proto__属性。
当代码读取某个属性时,一般会经过两个过程一个是在实例上搜索属性,搜索不到就通过__proto__属性到原型对象上搜索。
通过hasOwnProperty()方法,可以检测一个属性是存在实例中还是原型中,实例中返回true。
原型对象上的属性可以让所有实例共享,但是当属性为引用类型时就会容易产生问题。
function Person(){ } Person.prototype.names = ["yang", "zhang"]; var people1 = new Person(); var people2 = new Person(); people1.names //["yang", "zhang"] people2.names //["yang", "zhang"] people1.names.push("test"); //因为属性共享,而且是引用类型,所以names改变了 people1.names //["yang", "zhang", "test"] people1.names //["yang", "zhang", "test"]
实例一般应该有自己的全部属性,这里没有
组合使用构造函数模式和原型模式
function Person(name, age){ //构造函数继承的属性是独有的 this.name = name; this.age = age; this.friends = ["yang", "zhang"]; } Person.prototype.sayName = function(){ //通过原型模式来共享方法 alert(this.name); } //创建实例,实例不共享属性,共享方法 var people1 = new Person("yangxunwu", 24); var people2 = new Person("hexiaoming", 6); //访问引用类型 people1.friends; //["yang", "zhang"] people1.friends; //["yang", "zhang"] //为添加元素 people1.friends.push("wang"); people1.friends; //["yang", "zhang","wang"] 元素被添加到people1的属性中,因为构造函数不共享属性 people1.friends; //["yang", "zhang"] people1.sayName === people2.sayName //true。共享方法
动态原型模式:
function Person(name, age){ //动态原型模式 this.name = name; this.age = age; this.friends = ["yang", "zhang"]; if(Person.prototype.sayName != "function"){ //动态加载,只在第一次添加原型方法 Person.prototype.sayName = function(){ alert(this.name); } }; }
只在第一次调用构造函数时执行,之后原型已经完成初始化。
寄生构造函数模式:
function Person(name, age){ var obj = new Object(); //生成一个Objdetde对象 obj.name = name; obj.age = age; obj.sayName = functon(){ alert(this.name); } return obj; //返回的一直是Object的对象。 } var people = new Person("yangxunwu", 24); //与工厂模式的区别,坑 people.sayName(); //yangxunwu
返回的对象与构造函数或者构造函数的原型没关系,而且返回的一直是Object类型。只是把外部干的事放到内部干。
稳妥构造函数:
function Person(name, age){ var obj = new Object(); //定义私有变量和函数 obj.doSomething = function(){ alert(name); //定义可以访问私有变量和函数的方法,没有引用this } return obj; //返回对象,现在只有这个对象可以访问这些私有变量和函数。 } var people = Person("yangxunwu", 24); //没使用new people.sayName(); //yangxunwu
稳妥构造就是没有公共的属性,不引用this,防止数据被其他应用程序破坏。稳妥构造函数与寄生构造函数不同:
- 新创建的对象方法不引用this
- 不使用new操作符来调用构造函数。
时间: 2024-10-05 08:59:34