js创建对象方法及其优缺点

亦凉 2022-12-30 13:40 130阅读 0赞
  1. Object函数

    var obj = new Object();
    obj.name = “XXX”;
    obj.sayName = function(){

    1. console.log(this.name);

    };

  2. 对象字面量

    var obj = {

    1. name:"aa",
    2. sayName:function(){
    3. console.log(this.name);

    }
    };

缺点:前两种方式会产生大量重复代码

  1. 工厂模式:抽象创建具体对象的过程,用函数来封装以特定接口创建对象的细节,不适用new关键字

    function createObject(name,age){

    1. var o = new Object();
    2. o.name = name;
    3. o.age = age;
    4. o.sayName = function(){
    5. console.log(this.name);

    };
    return o;
    }
    var obj1 = createObject(“xiao”,22);
    var obj2 = createObject(“xi”,22);

缺点:虽然解决了创建多个相似对象的问题,但是没有解决对象识别的问题(怎样知道对象类型)

  1. 构造函数模式

    function Person(name,age){

    1. this.name = name;
    2. this.age = age;
    3. this.sayName = function(){
    4. console.log(this.name);
    5. }

    }
    var obj1 = new Person(“xiao”,22);
    var obj2 = new Person(“xi”,22);
    //实例的constructor属性指向构造函数
    obj1.constructor == Person;//true

跟3相比没有显示创建对象,直接将属性赋值给this对象,没有return语句
以这种方式调用构造函数经过一下四个阶段:1.创建新对象 2.将构造函数的作用域赋给新对象(this会指向该对象) 3.给新对象添加属性 4.返回新对象
构造函数相比于工厂函数的优点:可以将实例标识为一种特定的类型,用instanceof可检测该实例是否是构造函数的实例
缺点:每构造一个实例,构造函数中的方法都会在实例上重新创建一遍。

  1. 原型模式:我们创建的每个函数都有一个prototype属性,该属性是一个指针,指向一个对象,该对象包含可以由特定类型的所有实例共享的属性和方法。使用原型对象的好处是所有对象实例共享它所包含的属性和方法。默认情况下,所有的原型函数对象都会自动获得一个constructor(构造函数)属性,该属性指向包含一个指向prototype属性所在函数的指针,即构造函数.prototype.constructor指向该构造函数。构造函数创建实例时,实例内部有指针指向构造函数的原型对象(实例的隐式原型对象指向构造函数的显式原型对象)实例.proto==构造函数.prototype;可通过isPrototypeOf()方法来确定对象之间是否存在该种关系。
    hasOwnProperty();用于检测一个属性存在于实例中还是原型中,只有给定属性存在与对象实例中,才会返回true
    in操作符(会遍历原型上的属性);使用hasOwnProperty()和in操作符就能确定属性到底是存在于实例中还是原型中:例

    function hasPrototypeProperty(obj,name){

    1. return !obj.hasOwnProperty(name) && (name in obj);//返回true表示在原型中,返回false表示在实例中

    }

    function Person(){
    }
    Person.prototype.name = ‘xiao’;
    Person.prototype.sayName = function(){

    1. console.log(this.name);

    }
    /*
    简洁写法
    function Person(){
    }
    Person.prototype={

    1. name:'xxx';
    2. sayName:function(){
    3. console.log(this.name);

    }//这种写法会使constructor不指向Person,这些相当于重写了prototype,会指向Object
    改进:
    Object.defineProperty(Person.prototype,”constructor”,{

    1. enumerable:false,
    2. value:Person,

    });//constructor属性重新指向Person
    }
    */
    person1 = new Person();
    console.log(Person.prototype.isPrototypeOf(person1));//true
    console.log(person1.hasOwnProperty(“name”));//false,name存在于原型对象上
    person1.name = “own”;
    console.log(person1.hasOwnProperty(“name”));//true,name存在于实例上
    delete person1.name;
    console.log(person1.hasOwnProperty(“name”));//false,name存在于原型对象上

缺点:所有实例对象取得的都是相同的属性值,没有初始化参数,最大的问题还是共享,一个实例修改原型中的引用类型,会导致其他实例中的引用类型一起改变
例:

  1. function Person(){
  2. }
  3. Person.prototype={
  4. constructor:Person,//这种写法会让constructor变成可枚举的
  5. name:'xxx',
  6. friends:["aa","bb"];
  7. sayName:function(){
  8. console.log(this.name);
  9. }
  10. var pe1 = new Person();
  11. pe1.friends.push("bbb");
  12. var pe2v = new Person();
  13. console.log(pe2v.friends);//"aa","bb","bbb"
  14. pe1.friends === pe2v.friends;//true
  1. 组合构造函数和原型模式:构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性
    例:

    function Person(name,age,job){

    1. this.name = name;
    2. this.age = age;
    3. this.job = job;
    4. this.friends = ["aa","bb"];

    }

    Person.prototype = {

    1. constructor:Person,
    2. sayName:function(){
    3. console.log(this.name);

    }
    /*
    或下面这种写法
    Person.prototype.sayName = function(){

    1. console.log(this.name);

    }
    */
    var p1 = new Person(“ww”,22,”engineer”);
    var p2 = new Person(“xx”,23,”teacher”);
    p1.friends.push(“zz”);
    alert(p1.friends);//“aa,bb,zz”
    alert(p2.friends);//“aa,bb”
    alert(p1.friends === p2.friends);//false
    alert(p1.sayName===p2.sayName);//true
    }

  2. 动态原型模式:将所有信息都封装在构造函数中,通过在构造函数中初始化原型同时保持使用构造函数和原型的有点,通过检查某个方法是否存在,再决定是否需要初始化原型
    例:

    function Person(name,age,job){

    1. this.name = name;
    2. this.age = age;
    3. this.job = job;

    if(typeof this.sayName != “function”){

    1. Person.prototype.sayName = function(){
    2. alert(this.name);

    };
    }
    }
    var friend = new Person(“ww”,22,”engineer”);

只有当sayName方法不存在的时候才会将它添加到原型中,在初次调用构造函数时才会执行

  1. 寄生构造函数模式:创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后返回新创建的对象;和工厂函数的写法一致,但使用new关键字

    function CreateObject(name,age){

    1. var o = new Object();
    2. o.name = name;
    3. o.age = age;
    4. o.sayName = function(){
    5. console.log(this.name);

    };
    return o;
    }
    var obj1 =new CreateObject(“xiao”,22);
    obj1.sayName();//xiao

构造函数在不返回值的情况下,默认会返回新的对象实例,通过在构造函数末尾添加一个return语句,可以重写调用构造函数时的返回值,该模式可在特殊情况下为对象创建构造函数。该模式返回的对象与构造函数或者与构造函数的原型属性之间没有依赖关系,构造函数返回的对象于在构造函数外部创建的对象没什么不同,所以不能依赖instanceof来检测对象

  1. 稳妥构造函数模式:稳妥模式:没有公共属性,其方法也不引用this对象,适合用在安全的环境中(这些环境会禁止new和this),该模式于寄生构造函数类似的模式,有两点不同:1.新创建对象的实例方法不引用this,不使用new操作符调用构造函数

    function Person(name,age,job){

    1. var o = new Object();
    2. //可以在这里定义函数和变量
    3. o.sayName = function(){
    4. console.log(this.name);

    };
    return o;
    }
    //以上函数除了sayName方法外,没有其他办法访问name的值

发表评论

表情:
评论列表 (有 0 条评论,130人围观)

还没有评论,来说两句吧...

相关阅读