zoukankan      html  css  js  c++  java
  • 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高级程序设计》
  • 相关阅读:
    Spring spEL
    Spring 使用外部部署文件
    Spring 自动装配
    spring 属性配置细节
    hdu 1054 Strategic Game
    fzu 2037 Maximum Value Problem
    将博客搬至CSDN
    HDU 4714 Tree2Cycle
    HDU 1009 The Shortest Path in Nya Graph
    POJ 1942 Paths on a Grid 组合数的优化
  • 原文地址:https://www.cnblogs.com/hlwyfeng/p/6077366.html
Copyright © 2011-2022 走看看