js创建对象的几种方式

一、工厂模式

一个函数,将对象的属性作为参数传给该函数,返回一个对象

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("cwj","20","Doctor");

没有把函数的作用域赋值给新对象,新对象的所有方法和属性都属于windows对象

仅仅解决了创建对象的问题,并不知道创建的是一个什么类型的对象

 

二、构造函数模式(new操作符)

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

var person1=new Person("cwj","20","Doctor");

与工厂模式的区别:

  1. 没有显式创建一个对象(但不代表没有对象)
  2. 没有return语句(但不代表没有返回一个对象)
  3. 将构造函数的作用域赋给新对象(既this指向这个新对象)

!!!构造函数与普通函数唯一的区别是调用方式不同,任何函数,只要用new操作符来调用就会被当作是构造函数。

三、原型模式

构建的每一个函数都有一个prototype(原型)属性,指向原型对象,而原型对象又有一个constructor属性指向原型的构造函数。(Person.prototype.constructor=Person)

!!!这个原型对象的作用是包含所有实例共享的属性和方法。

function Person(){
    Person.prototype.name="cwj";
    Person.prototype.age=21;
    Person.prototype.sayName=function(){
       alert(this.name);
    }
}
var peason1=new Person();
person1.sayName();//输出“cwj”

//既所有的Person的实例在创建的同时就已经拥有name=“cwj”和age=21两个属性了

当然实例也能拥有自己的属性和方法,但是当实例的属性和方法和原型中的属性和方法同名时,实例的属性和方法将会覆盖原型中的属性和方法(既不能访问存在原型中的属性和方法的值),这种情况下,可以使用delete操作符删除实例中与原型同名的属性和方法,这样便能重新访问原型中的属性和方法了

原型模式中常用到的判断方法:

(1).isPrototypeOf()——判断对象之间是否存在原型关系

Person.prototype.isPrototypeOf(person1);//true,Person.prototype是 peason1的原型

(2)Object.getPrototypeOf()——返回实例的原型对象

Object。getPrototypeOf(person1);//Person.prototype

(3).hasOwnproperty()——判断实例是否拥有该属性(既该属性是存在实例中,而不是存在原型对象中,若存在原型对象中,则返回false)

person1.hasOwnProperty("name");

(4)in操作符——同样也是用来判断实例是否拥有该属性,与hasOwnproperty()不同的是,无论属性是在实例中还是在原型对象上,该方法都会返回true

(5)获取可枚举属性

  • for in——获取原型和实例上的所有属性
  • object.keys(传入对象)——只获取传入对象的属性,如果传入对象是实例,则只会去该实例的属性,不包括原型对象上的

四、组合使用构造方法和原型模式(最广泛使用的方法)、

构造函数定义的属性不能共享,原型模式定义的引用类型属性容易被某一实例覆盖后而导致所有实例的属性都发生变化(例如数组属性,person1修改原型对象上的数组属性,person2的数组属性也会跟着被修改)

基于上面两点缺陷,所以出现了组合使用方法!

用构造函数定义实例属性(实例自己的属性,和其他实例无关);原型对象定义共享属性

五、动态原型模式

在构造函数中判断是否有初始化原型对象的必要

function Person(name,age,job){
    this.name=name;
    this.age=age;
    this.job=job;
    if(typeOf this.sayName !="function"){
        Person.prototype.sayName=function(){
            alert(this.name);
        }
    }
    /*只有在sayName()不存在的情况下才会在原型对象中创建这个函数,只有初次调用构造函数时这段代码才会生效(既原型已完成初始化)所以当第二次调用构造函数时,不会再执行这段代码*/
}

六、寄生构造函数(一般不建议使用)

除了使用new操作符,并把使用的包装函数叫做构造函数外,与工厂模式没有区别,该函数的作用仅仅是封装创建对象的代码,然后再返回新创建的对象

七、稳妥构造函数形式

所谓稳妥对象是指没有公共属性,而其方法也不引用this的对象。适合用于安全环境

function Person(name.age,job){
    var o=new Object();
    //这里可以定义私有变量和函数
    
    o.sayName=function(){
        alert(name);
    };
    
    //返回对象
    return o;
}
//除了sayName()方法外,没有其他办法可以访问其数据成员了

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值