js 对象建立的几种方法

对象在全部编程语言中都是核心内容在js中他的建立方式也是多种多样,每一种建立方式都有其利弊,下面简单总结一下;编程

Object 内置对象建立

最简单的两种方式之一,直接利用系统内置的Object 来建立,系统内置Object 只有不多的方法属性,用它建立十分安全安全

var person1=new Object();
person.name='xiaoming';
person.age='18';
person.sayName=function (){
    alert(this.name)
}

var person2=new Object();
person.name='xiaohong';
person.age='16';
person.sayName=function (){
    alert(this.name)
}

person1.sayName();//xiaoming
person2.sayName();//xiaohong

这种方式优缺点很明显,优势是简单,不须要额外的代码,直接建立就好,方法属性都是挂在本身身上;缺点也很明显,这东西一次只能建立一个,不适合批量建立,假设遇到重复建立那就让人崩溃;编程语言

字面量{}建立

这个跟上面的利用Object 内置对象建立是一个意思,本质也就是同样,{}这个东西也就是Object 的语法糖而已;函数

var person1={
    name:'xiaoming',
    age:'18',
    sayName:function(){
        alert(this.name);
    }
}
person.sayName();


var person2={
    name:'xiaohong',
    age:'16',
    sayName:function(){
        alert(this.name);
    }
}
person1.sayName();

person2.sayName();

优缺点不用说,跟上面就是一个玩意儿;测试

有了上面的缺点天然就要想办法克服,对于相同的东西人们喜欢抽出来,类似的就集合封装,因而有了这种东西this

工厂方式

function ceartPerson(name,age){
    var person={
        name:name,
        age:age,
        sayName:function(){
            alert(this.name)
        }
    }
    return person;
}
var person1=ceartPerson('zhangshan',18);
person1.sayName();//zhangshan

var person2=ceartPerson('lishi',20);
person2.sayName(); //lishi

咱们建立了一个函数用来返回所须要的对象,把这个对象所须要的信息经过传参的方式传入来构造不一样的对象;咱们在函数ceartPerson里面有一个原料person对象,咱们就是经过改变这个原料person对象的属性来构造一个个对象,这种做业方式很像工厂的流水线做业,外面来一个,里面加工一个,因此这种方式也被形象的成为工厂模式;prototype

可是这种方式也是有本身的缺点的,第一个有些难为强迫症患者,就是没有new 关键字,对于人们建立对象的固有认知不同;
第二个相对致命,一个神奇的事情code

alert(person1.sayName===person2.sayName) //false;

这就很郁闷了,这表明着什么呢,这就意味着从这个工厂里面出来的对象每个都是独立个体,互不影响,他们之间的方法并非引用同一个地方,可是明明功能都是同样的,因此这种方式会极大的消耗咱们的系统资源,这显然不是咱们乐意看到的对象

第三个缺点,没法使用instanceof 来判断本身的来历;在前面提到过instanceof 能够用来断定 对象的隐式原型和目标的原型对象是否在一条原型链上(更加官网的说法 instanceof运算符用于测试构造函数的prototype属性是否出如今对象的原型链中的任何位置),如今使用工厂模式建立的对象却没法使用instanceof,这就致使原型链混乱,这显然也不是咱们乐意看到的;原型链

var obj={};
console.log(obj instanceof Object) //true

console.log(person1 instanceof ceartPerson) //false;

构造函数

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

var person1=new CreatPerson('zhangshan',18);
var person2=new CreatPerson('lishi',16);

person1.sayName(); //zhangshan;

构造函数,主语是函数,因此这种东西也就是一个函数,跟其余函数没什么区别,只是做用有点儿特殊而已,是用来建立对象而已,就像医生也仍是一我的,只是工做是救人,因此咱们管他叫医生,管教书育人的人叫老师,因此函数该有的操做构造函数都有;
这种作法比上面的工厂模式略有简化,首先在构造函数内部并灭有显式的建立对象,也没有显示的返回对象这一步,
全部的操做都在外部的new 关键字作了
首先new 会在构造函数里面偷偷的建立一个对象,而后使用call 方法转换this 指向为该对象,而后在偷偷的返回该对象;固然这只是简单描述构造函数的建立过程;

console.log(person1 instanceof CreatPerson) //true
console.log(person1.sayName===person2.sayName) //false;

结果很明显,每个出来的都是单独的实例对象,方法仍是没有共同,一样存在了上面的问题,可是他却解决了原型链的问题,可使用instanceof 来断定他的来源;

原型模式

前面提到的原型链顶端的存在,会让这条原型链下面的存在都具备相同的方法和属性,咱们能够利用这个特性来建立对象试试

function CreatPerson(){};//建立一个构造函数,主要来利用这个玩意儿产生原型对象;
CreatPerson.prototype.name='zhangshan';
CreatPerson.prototype.age='18';
CreatPerson.prototype.sayName=function(){
    alert(this.name)
}
var person1=new CreatPerson();
person1.sayName();//zhangshan;

var person2=new CreatPerson();
person2.name='lishi';
person2.sayName(); //lishi;

alert(person1 instanceof CreatPerson) //true;
console.log(person2.sayName===person1.sayName) //true;

结果证实 从Person出来的实例都是对他的高度引用,新对象实例的属性和方法能够重写覆盖;这样作到个性化的操做;全部的实例均能共享一样的原型对象,因此也就解决了重复建立的问题,也解决了原型混乱的问题;可是缺点也很明显,没办法初始化参数,用上面的例子说明就是全部从CreatPerson 出来的对象实例的name 属性初始化都是zhangshan,这是至关危险的操做;

混合构造模式

既然构造函数能够初始化参数,原型模式能够搞定原型链混乱,能不能想办法综合一下呢?

function CreatPerson(name,age){
    this.name=name;
    this.age=age;
}
CreatPerson.prototype.sayName=function(){
    alert(this.name)
}
var person1=new CreatPerson('zhangshan',18);
person1.sayName()//zhanshan

var person2=new CreatPerson('lishi',16);
person2.sayName()//lishi

console.log(person1 instanceof CreatPerson); //true
console.log(person1.sayName===person2.sayName);//true

能够看到这种原型混合构造模式可以有效的解决建立对象过程的问题,使用构造函数加属性,使用原型加方法;这样既能搞定初始化参数的问题,也能解决方法重复建立的问题;他是一种较为稳妥的方法,缺点就是写着麻烦了点儿

相关文章
相关标签/搜索