Javascript 创建对象总结

使用JavaScript创建对象的方法有很多,现在就来列举一下。

1、使用Object构造函数来创建一个对象

下面代码创建了一个person对象,并打印出了name的属性值。

  var person = new Object();
    person.name="Joe";
    person.age=25;
    alert(person.name);
    alert(person["name"])

2、使用对象字面量创建一个对象

var person =  {
        name:"Joe",
        age:25
    };
    alert(person.name);
    alert(person["name"]);

3、使用工厂模式创建对象

返回带有属性和方法的person对象。

function createPerson(name, age){
    var o = new Object();
    o.name=name;
    o.age=age;
    o.sayName=function(){
        alert(this.name);
    };
    return o;
}
var people=createPerson("kevin",31);
people.sayName();

4、使用自定义构造函数模式创建对象

这里注意命名规范,作为构造函数的函数首字母要大写,以区别其它函数。这种方式有个缺陷是sayName这个方法,它的每个实例都是指向不同的函数实例,而不是同一个。

function Person(name,age){
    this.name=name;
    this.age=age;
    this.sayName=function(){
        alert(this.name);
    };
}

var person = new Person("Joe",25);
person.sayName();

5、使用原型模式创建对象

解决了方法4中提到的缺陷,使不同的对象的函数(如sayFriends)指向了同一个函数。但它本身也有缺陷,就是实例共享了引用类型friends,从下面的代码执行结果可以看到,两个实例的friends的值是一样的,这可能不是我们所期望的。

function Person(){
}

Person.prototype = {
    constructor : Person,
    name:"Joe",
    age:25,
    friends:["Json","Jack"],
    sayFriends:function(){
        alert(this.friends);
    }
};

var person1 = new Person();
person1.friends.push("Ares");//这里把构造函数的原型给改了
person1.sayFriends();//Json,Jack,Ares
var person2 = new Person(); 
person2.sayFriends();//Json,Jack,Ares

6、组合使用原型模式和构造函数创建对象

解决了方法5中提到的缺陷,而且这也是使用最广泛、认同度最高的创建对象的方法。

能够把可以重用的部分迁移到原型链中,而不可重用的则设置为对象的自身属性。

function Person(name,age){
    this.name=name;
    this.age=age;
    this.friends=["Json","Jack"];
}

Person.prototype.sayFriends=function(){
    alert(this.friends);
};

var person1 = new Person("Andy",26);
var person2 = new Person("Tom",27);
person1.friends.push("Joe");
person1.sayFriends();//Json,Jack,Joe
person2.sayFriends();//Json,Jack

7、仅从原型继承法

和“原型链继承法”相比,本方法的优点在于,提高了运行时的效率,没有创建新对象出来。

Human.prototype 的修改都会影响到 Animal.prototype,因为两者指向的是同一个对象。

一个致命缺点就是,无法修正子类构造的对象的 constructor。

var Animal = function(name){
    this.name = name;
};
Animal.prototype.jump = function(){
    console.log('jumped');
};
var Human = function(name){
    this.name = name;
};
Human.prototype = Animal.prototype;
var man = new Human('HaoyCn');
man.jump();

8、原型链继承法

var Animal = function(name){
    this.name = name;
};
Animal.prototype.jump = function(){
    console.log('jumped');
};
var Human = function(name){
    this.name = name;
};
// 这一步会使得,Human.prototype.constructor = Animal,所以需要重新手动重定向。而且这里会产生一个undefied属性name,因为没有传入参数。
Human.prototype = new Animal;
//如果不更改,通过`Human`构造器构造出来的对象的构造器会变成`Animal`而不是`Human`
Human.prototype.constructor = Human;

var man = new Human('HaoyCn');
man.jump();

9、临时构造器继承法

“临时构造器继承法”使用一个中介函数,避免了Animal.prototype 会因对 Human.prototype 的修改而改变,也避免了产生未定义的属性。

var Animal = function(name){
    this.name = name;
};
Animal.prototype.jump = function(){
    console.log('jumped');
};
var F = function(){};
F.prototype = Animal.prototype;
var Human = function(name){
    this.name = name;
};
Human.prototype = new F;
Human.prototype.constructor = Human;
Human.prototype.sing = function(){
    console.log('Mayday');
};
var man = new Human('HaoyCn');
man.jump();
man.sing();

10、构造器借用法

以上继承法共通的一个缺点在于,Human 构造器构造的对象虽然可以共用 Animal.prototype,但对于 name 属性而言,Human 构造器只能自己再写一遍构造 name 属性,为什么不把初始化属性的方法也共(借)用呢?

构造器借用法应运而生。现在我们把 name 属性的创建还是交给 Animal,然后再为 Human 增加 country 属性。我们在“临时构造器法”基础上进一步完善之。

var Animal = function(name){
    this.name = name;
};
Animal.prototype.jump = function(){
    console.log('jumped');
};
var F = function(){};
F.prototype = Animal.prototype;
var Human = function(){
    Animal.apply(this,arguments);
    this.country = arguments[1];
}
Human.prototype = new F;
Human.prototype.constructor = Human;
var man = new Human('HaoyCn','China');
console.log(man.country);// China

11、动态原型模式

这个模式的好处在于看起来更像传统的面向对象编程,具有更好的封装性,因为在构造函数里完成了对原型创建。这也是一个推荐的创建对象的方法。

function Person(name,age){
    //属性
    this.name=name;
    this.age=age;
    this.friends=["Json","Jack"];
    //方法
    if(typeof this.sayName !="function"){
        Person.prototype.sayName=function() {
            alert(this.name);
        };
        Person.prototype.sayFriends=function() {
            alert(this.friends);
        };
    }
}

var person = new Person("Joe",25);
person.sayName();
person.sayFriends();

另外还有两个创建对象的方法,寄生构造函数模式和稳妥构造函数模式。由于这两个函数用得比较少。

12、利用Object.create()、call()组合继承创建对象

利用Object.create()call()继承父类得实例属性方法和原型属性方法。

Object.create()兼容IE9及以上。

function inherit(superType,subType){
    var _prototype=Object.creat(superType.prototype);//获取父类prototype对象副本
    _prototype.constructor=subType;//修改构造器为子类本身
    subType.prototype=_prototype;//修改子类prototype对象
}

function Parent(){
    this.age=25;
} 

Parent.prototype.sayName=function(){
    alert(this.name);
}

function Child(name){
    this.name=name;
    Parent.call(this);//获取父类得实例变量
}

inherit(Parent,Child);

Child.prototype.sayAge=function(){
    alert(this.age);//如果需要在Child的原型上添加方法,一定要在inherit(Parent,Child)之后,否则会被覆盖
}

var child=new Child();
console.log(child.age);
child.sayName();

13、利用深拷贝继承创建对象

var Web={
    target:"浏览者访",
    jiaocheng:["css教程","div教程","js教程"]
    }
var Antzone={
    webName:"蚂蚁部落",
    };

function deepCopy(f, c) {
    for (var prop in f) {
        if (typeof f[prop] === 'object') {
            c[prop] = (f[prop].constructor === Array) ? [] : {};
            deepCopy(f[prop], c[prop]);
        } else {
            c[prop] = f[prop];
          }
    }
    return c; 
}
var obj=deepCopy(Web,Antzone);
console.log(obj.target);
console.log(obj.webName);
obj.jiaocheng.push("jquery教程");
console.log(Web.jiaocheng);
console.log(obj.jiaocheng);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值