1.Javascript创建对象的几种方式?
1.使用Object构造函数创建对象
var person = new Object();
person.name = "wanghuan";
person.age = 23;
person.sayName = function(){
alert(this.name);
};
2.使用对象字面量创建对象
var person = {
name:"wanghuan",
age:23,
sayName:function(){
alert(this.name);
}
};
上述两个方法都是创建单个对象,要想批量创建对象,则使用下列方法
3.使用工厂模式创建对象
工厂模式的优点:
发明了一种函数,用函数来封装以特定接口创建对象的细节。
工厂模式的问题:
虽然解决了多个相似对象的问题,但却没有解决对象识别的问题。
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("wanghuan",22,"software engineer");
var person2 = createPerson("shuguang",22,"army");
4.使用构造函数模式创建对象
构造函数模式的优点:
自定义的构造函数意味着将来可以把它的实例标识为一种特定的类型,这正是构造函数模式胜过工厂模式的地方。
function Person (name,age,job) {//构造函数,习惯性的第一个字母大写
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
}//其实有this对象在,根本不用在执行代码前把函数绑定到特定对象上边
}
var person1 = new Person("wanghuan",22,"software engineer");
var person2 = new Person("shuguang",22,"army");
构造函数模式的缺点:
构造函数主要问题就是每个方法都要在每个实例上重新创建一遍,这种方法创建函数,会导致不同的作用域链和标识符解析。
因此,用
function Person (name,age,job) {//构造函数,习惯性的第一个字母大写
this.name = name;
this.age = age;
this.job = job;
}
function sayName(){
alert(this.name);
}//把sayName()函数的定义转移到了构造函数外部,对象共享在全局作用域中定义的同一个函数
var person1 = new Person("wanghuan",22,"software engineer");
var person2 = new Person("shuguang",22,"army");
但还有缺点:
1. 全局作用域定义的函数每次被一个对象调用,全局作用域不是名副其实
2. 对象需要定义很多方法,要是全部都定义成全局函数,自定义的引用类型就丝毫无封装性可言。
5.使用原型模式创建对象
原型模式的缺点
所有属性的共享会导致所有实例默认一样的属性值,不合常理
创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向函数的原型对象。
每次读取某个对象的某个属性的时候,需要执行搜索:
1.搜索对象实例本身,在实例中找到给定名字的属性,则返回属性的值,使用delete属性可以删除实例属性。
2.若没找到,则继续搜索指针指向的原型对象。
言外之意,对象实例本身的属性优先。
ps:用hasOwnProperty来判断属性是否存在于实例中或者原型中
此图为添加实例属性的情况:
function Person () {
}
Person.prototype.name = "wanghuan";
Person.prototype.age = "22";
Person.prototype.job = "software engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
var person2 = new Person();
person1.name = "shuguang";
alert(person1.name);//shuguang---先搜索实例对象,就返回
alert(person1.hasOwnProperty("name"));//true
alert(person2.name);//wanghuan--原型对象属性返回
delete person1.name;//delete操作符删除实例属性
alert(person1.hasOwnProperty("name"));//false
alert(person1.name);//wanghuan--原型对象属性返回
原型模式更简单的语法
以对象字面量形式创建的新对象
function Person () {
}
Person.prototype = {
name:"wanghuan",
age : "22",
job : "software engineer",
sayName: function(){
alert(this.name);
}
};
6.原型模式和构造函数模型的组合使用创建对象
//构造函数
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ["a","b"];
}
//原型对象
Person.prototype = {
constructor:Person;
sayName:function(){
alert(this.name);
}
}
var person1 = new Person("wanghuan",22,"software engineer");
var person2 = new Person("shuguang",22,"army");
person2.friends.push("c");
alert(person1.friends);//a,b
alert(person2.friends);//a,b,c
alert(person1.sayName === person2.sayName);//true
//说明两者的函数指针相同
7.动态原型模式
动态原型模式的优点
1.看起来更像传统的面向对象编程,具有更好的封装性
2.初次调用构造函数才可执行下面的if判断方法
3.不需要对每一个方法进行if检查,只需要检查其中一个即可
function Person(name,age,job)
{
//属性
this.name=name;
this.age=age;
this.job=job;
this.friends=["shu","guang"];
//方法,不需要对每一个方法进行if检查,只需要检查其中一个即可
if(typeof this.sayName !="function")
{
Person.prototype.sayName=function()
{
alert(this.name);
};
Person.prototype.sayFriends=function()
{
alert(this.friends);
};
}
}
var person = new Person("wanghuan",23,"SE");
person.sayName();
person.sayFriends();