• JavaScript创建对象


    最佳方式

    原型模式与构造模式组合使用

    先上代码:

    function Person(name,age,salary){
      this.name = name;
      this.age = age;
      this.salary = salary;
      this.people = ["people1","people2"];
    }
    
    Person.prototype = {
      constructor:Person,
      sayName:function(){
        console.log(this.name);
      }
    }
    
    var p1 = new Person("name1","20","5000");
    var p2 = new Person("name2","22","8000");
    
    p1.people.push("people3");
    console.log(p1.people);
    console.log(p2.people);
    

    运行结果:

    Array [ "people1", "people2", "people3" ]
    Array [ "people", "people" ]
    

    这是创建对象最常用也是认同度最高的方式,把可共享的方法和属性放在prototype原型对象里面,把实例属性放在构造函数中。

    动态原型模式

    这种创建对象的模式,只写一个构造函数,而把原型放在构造函数中作为初始化用,这种结构就有点像java创建类一样,也是一种很好的创建对象的模式,我们来看一下:

    function Person(name,age,salary){
      this.name = name;
      this.age = age;
      this.salary = salary;
    
      if(typeof this.sayName != "function"){
        Person.prototype.sayName = function(){
          console.log("Hello, " + this.name);
        }
        Person.prototype.saySalary = function(){
          console.log("My salary is " + this.salary);
        }
      }
    }
    
    var p1 = new Person("name1","20","8000");
    var p2 = new Person("name2","21","7000");
    p1.sayName();
    p1.saySalary();
    
    p2.sayName();
    p2.saySalary();
    

    运行结果:

    Hello, name1  
    My salary is 8000 
    Hello, name2  
    My salary is 7000
    

    这种模式不能用字面量来重写原型。如果你尝试使用下面的代码来编写:

    function Person(name,age,salary){
      this.name = name;
      this.age = age;
      this.salary = salary;
    
      if(typeof this.sayName != "function"){
    
        Person.prototype = {
          constructor : Person,
          sayName : function(){
            console.log("Hello, " + this.name);
          },
          saySalary : function(){
            console.log("My salary is " + this.salary);
          }
        }
      }
    }
    
    var p1 = new Person("name1","20","8000");
    var p2 = new Person("name2","21","7000");
    p1.sayName();
    p1.saySalary();
    
    p2.sayName();
    p2.saySalary();
    

    运行结果:

    TypeError: p1.sayName is not a function
    

    因为原型的重写是在创建了对象之后进行的,重写后的原型实际上是一个新的原型对象(重新创建一个,原来的还在,它们的constructor都指向Person),而实例的prototype指针还是指向原来的原型对象(里面没有其他属性和方法,因为属性和方法写在新的原型对象上),所以运行的时候,在实例对象中找不到sayName方法,在原型对象中也找不到sayName方法,即sayName未定义,所以在调用p1.sayName()方法时就报错,说sayName不是一个方法。

    我们可以看下面的例子来深入理解一下:

    function Person(){};
    
    // 在之前创建
    var p1 = new Person();
    
    Person.prototype = {
      constructor:Person,
      name:"name1",
      age:"20",
      sayName:function(){
        console.log(this.name);
      }
    };
    
    // 在之后创建
    var p2 = new Person();
    p2.sayName(); //name1
    
    p1.sayName(); //error
    

    常用的方法

    我们以下面这段代码为例:

    function Person(name,age,salary){
      this.name = name;
      this.age = age;
      this.salary = salary;
      this.people = ["people1","people2"];
    }
    
    Person.prototype = {
      constructor:Person,
      publicWork:"Teacher",
      sayName:function(){
        console.log(this.name);
      }
    }
    
    var p1 = new Person("name1","20","5000");
    var p2 = new Person("name2","22","8000");
    

    删除实例属性 delete

    p1.publicWork = "Doctor";
    console.log(p1.publicWork);
    p1.publicWork = null;
    console.log(p1.publicWork);
    delete p1.publicWork;
    console.log(p1.publicWork);
    

    运行结果:

    Doctor  
    null  
    Teacher
    

    检测对象类型 instanceof

    console.log(p1 instanceof Person); //true
    console.log(p2 instanceof Person); //true
    

    判断原型对象与实例之间是否联系 isPrototypeOf()

    console.log(Person.prototype.isPrototypeOf(p1)); //true
    console.log(Person.prototype.isPrototypeOf(p2)); //true
    

    获得原型对象 Object.getPrototypeOf()

    console.log(Object.getPrototypeOf(p1) == Person.prototype); //true
    console.log(Object.getPrototypeOf(p2).publicWork); //Teacher
    

    注意:这是 ECMAScript5 的新方法,IE9+、其他主流浏览器支持。

    判断属性是否存在于原型对象中

    //函数作用:判断属性是否存在于原型对象中
    function isInPrototype(obj,param){
      if((param in obj) && !obj.hasOwnProperty(param)){
        return true;
      }else{
        return false;
      }
    }
    
    console.log(isInPrototype(p1,"publicWork")); //true
    console.log(isInPrototype(p2,"name")); //false
    
    • hasOwnProperty() 可以检测属性是否在实例中
    • in 可以检测属性是否存在,无论是在实例中还是在原型对象中

    通过以上方法的结合,即可判断属性是否存在于原型对象中。

    获得可枚举的属性和方法 Object.keys()

    先要了解:对于系统内置的属性一般是不可枚举的,如果重新创建覆盖原来的属性,那么就变成可枚举。

    console.log(Object.keys(p1));
    console.log(Object.keys(Person.prototype));
    

    运行结果:

    Array [ "name", "age", "salary", "people" ]
    Array [ "constructor", "publicWork", "sayName" ]
    

    其中constructor为覆盖的属性,所以变为可枚举。

    参考

    • 《JavaScript高级程序设计》
  • 相关阅读:
    小学生双倍快乐
    暑期随笔
    akm
    设计原型
    测试与优化
    小学生求求你别折磨程序员
    小学生快乐刷题
    枪在手,跟我走

    第一次团队作业
  • 原文地址:https://www.cnblogs.com/hlwyfeng/p/6077366.html
Copyright © 2020-2023  润新知