1. 最简单的创建对象方式就是创建一个Object实例,然后为它添加属性和方法
    1. var person = new Object();
    2. person.name = '张珈瑞';
    3. person.age = 24;
    4. person.sayName = function (){
    5. console.log(this.name)
    6. }

    通过这种方式就创建了一个对象,早期的开发人员经常使用这个模式来创建对象,几年后,对象字面量成为创建这种对象的首选模式。

    2.对象字面量创建对象

    1. var person = {
    2. name:'张珈瑞';
    3. age:24;
    4. sayName:function(){
    5. console.log(this.name)
    6. }
    7. }

    3.工厂模式创建对象

    1. function createPerson(name,age){
    2. var person = new Object();
    3. person.name = name;
    4. person.age = age;
    5. person.sayName = function(){
    6. console.log(this.name)
    7. }
    8. return person
    9. }
    10. var zhangjiarui = createPerson("张珈瑞",24);
    11. var zhangsan = createPerson("张三",24);

    优点:解决了多个相似对象的创建问题
    缺点:无法确定对象类型

    4.构造函数模式创建对象

    1. function Person(name,age){
    2. this.name = name;
    3. this.age = age;
    4. this.sayName = function(){
    5. console.log(this.name)
    6. }
    7. }
    8. var zhangjiarui = new person("张珈瑞",24);
    9. var zhangsan = new person("张三",18);

    构造函数和工厂模式的不同之处:

    • 1.没有显示的创建对象
    • 2.直接将对象的属性和方法赋值给了this
    • 3.没有return语句

    通过构造函数创建对象,必须使用 new 操作符。创建构造函数经历的4个步骤:

    • 1.创建一个对象
    • 2.将构造函数的作用域赋值给新对象(因此this就指向了新对象)
    • 3.执行构造函数中的代码(为这个对象添加属性和方法)
    • 4.返回新对象

    在上面的例子中,zhangjiarui和zhangsan都有一个constructor(构造函数)属性,该属性指向Person

    1. console.log(zhangjiarui.constructor == Person); //true
    2. console.log(zhangsan.constructor == Person); //true

    如果要检测一个对象的类型,还是instanceof

    操作符更可靠一些,在这个例子中创建的所有对象既是 Object 的实例,同时也是 Person的实例,这一点通过 instanceof 操作符可以得到验证

    1. console.log(zhangjiarui instanceof Person);//true
    2. console.log(zhangjiarui instanceof Object);//true
    3. console.log(zhangsan instanceof Person);//true
    4. console.log(zhangsan instanceof Object);//true

    优点:创建自定义的构造函数意味着将来可以将它的实例标识为一种特定的类型
    缺点:每个方法都要在每个实例上重新创建一遍,因为ECMAScript 中的函数是对象,因此每定义一个函数,也就是实例化了一个对象。

    5.通过原型创建对象

    1. function Person(){
    2. }
    3. Person.prototype.name = '张珈瑞';
    4. Person.portotype.age = '张三';
    5. Person.portotype.sayName = function(){
    6. console.log(this.name);
    7. }
    8. var zhangjiarui = new Person();
    9. var zhangsan = new Person();
    10. zhangjiarui.name = '张红';
    11. console.log(zhangjiarui.name);//张红---来自实例
    12. console.log(zhangsan.name);//张珈瑞---来自原型
    13. delete zhangjiarui.name;
    14. console.log(zhangjiarui.name);//张珈瑞 ---来自原型

    hasOwnProperty用来检测一个属性是存在实例中,还是存在原型中

    简化版原型创建对象(省略prototype)

    1. function Person(){
    2. }
    3. Person.prototype = {
    4. name:'张珈瑞';
    5. age:24
    6. sayName:function(){
    7. console.log(this.name)
    8. }
    9. }

    缺点:
    1.它省略了为构造函数传递初始化参数这一环节 , 所有实例在默认情况下都将取得相同的属性值
    2.无法将实例的属性单独出来,多个实例共享属性

    5.组合式创建对象(构造函数+原型)

    1. function Person(name,age){
    2. this.name = name;
    3. this.age = age;
    4. }
    5. Person.prototype = {
    6. constructor:Person
    7. sayName:function(){
    8. console.log(this.name)
    9. }
    10. }
    11. var zhangjiarui = new Person('张珈瑞',24);
    12. var zhangsan = new Person('张三',18);

    这种模式完美的解决了之前所存在的问题,构造函数将实例的属性单独出来,通过原型将实例的方法共享

    6.动态原型模式创建对象

    1. function Person(name,age){
    2. this.name = name;
    3. this.age = age;
    4. if(typeof this.sayName != "function"){
    5. Person.prototype = {
    6. constructor:Person
    7. sayName:function(){
    8. console.log(this.name)
    9. }
    10. }
    11. }
    12. }
    13. var zhangjiarui = new Person("张珈瑞",24);
    14. zhangjiarui.sayName();

    7.寄生构造函数创建对象(工厂+构造)

    1. function Person(){
    2. var per = new Object();
    3. per.name = '张珈瑞';
    4. per.age = 24;
    5. per.sayName = function(){
    6. console.log(this.name)
    7. }
    8. return per
    9. }
    10. var zhangjiarui = new Person("张珈瑞",24)
    11. zhangjiarui.sayName()

    这种方法用了实例化的时候用了new 在代码内部则和工厂模式完全一样