zoukankan      html  css  js  c++  java
  • 读javascript高级程序设计05-面向对象之创建对象

    1.工厂模式

    工厂模式是一种常用的创建对象的模式,可以使用以下函数封装创建对象的细节:

    function CreatePerson(name,age){
    var p=new Object();
      p.name=name;
      p.age=age;
      p.speak=function(){
      console.log("my name is "+p.name);
      }
      return p;
    }
    
    var p1=CreatePerson('Wang',15);
    p1.speak();
    
    var p2=CreatePerson("Li",18);
    p2.speak();

    特点:工厂模式实现了创建相似对象的功能,但是缺点是无法确定所创建出来对象的类型。

    2.构造函数

    ①使用构造函数可以创建对象:

    function Person(name,age){
      this.name=name;
      this.age=age;
      this.speak=function(){
      console.log("my name is "+this.name);
      }
    }

    构造函数和工厂模式区别的地方:没有在函数内显式的创建对象,而是直接将属性赋值给this;没有使用return语句返回。

    ②调用:使用new操作符调用构造函数创建对象。

    //作为构造函数调用
    var p1=new Person('Wang',15);
    p1.speak();// my name is Wang
    var p2=new Person("Li",18);
    p2.speak();// my name is Li


    调用过程经历了几个步骤:

    • 创建一个新对象;
    • 将构造函数的作用域赋给该对象,此时this也就指向了该对象;
    • 执行构造函数中的代码;
    • 返回该对象。

    另外,构造函数也可以作为普通函数调用,此时this指向的是window对象:

    Person('chen',15);
    window.speak();//my name is chen

    ③调用构造函数创建的对象,既是Person的实例,也是Object的实例。这一点上比工厂模式略胜一筹。

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

    ④缺点:方法speak要在每个实例上都创建一遍,不能进行共享。

    p1.speak==p2.speak;//返回false

    3.原型模式

    使用原型对象prototype的好处是可以让所有对象实例共享它所包含的属性和方法。

    function Person(){
    }
    
    //原型
    Person.protype={
      constructor:Person,
      name:'Tom',
      age:18,
      speak:function(){
      console.log('my name is '+this.name+',I am '+this.age);
      }
    }
    
    //调用
    var p1=new Person();
    var p2=new Person();
    console.log(p1.speak==p2.speak);//true
    console.log(p1.speak());//my name is Tom,I am 18

    可以看出Person的实例对象共享了属性和方法。

    isPrototypeOf()方法用来检测实例和原型对象之间的关系。

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

    当给实例设置与原型中同名的属性时,会给该实例对象新增一个属性,它会屏蔽访问原型中的同名属性值但不会修改原型中的属性值。

    p1.name='Cathy';
    console.log(p1.name);//Cathy
    console.log(p2.name);//Tom

    如果想重新访问原型中的属性值,可以使用delete操作符删除实例属性即可。

    delete p1.name;
    console.log(p1.name);//Tom
    console.log(p2.name);//Tom

    hasOwnProperty()方法:用来检测某属性是存在于实例中还是存在于原型中。仅当属性存在于实例中时,才返回true。

    in 操作符:只要对象存在某属性就返回true,无论是实例属性还是原型属性。

    p1.hasOwnProperty('name')//false
    "name" in p1;//true
    p1.name='Cathy';
    p1.hasOwnProperty('name')//true
    "name" in p1;//true
    p2.hasOwnProperty('name')//false
    "name" in p2;//true
    delete p1.name;
    p1.hasOwnProperty('name')//false
    "name" in p1;//true

    结合使用hasOwnProperty和in,可以判断属性是不是存在于原型中。

    function hasPrototypeProperty(object,name){
    return (!object.hasOwnProperty(name))&&(name in object);
    }
    var p1=new Person();
    console.log(hasPrototypeProperty(p1,'name'));//true
    p1.name='Peter';
    console.log(hasPrototypeProperty(p1,'name'));//false

    原型的动态性:对原型所做的修改能够立即从实例中体现出来。

    function Person(){
    }
    var p=new Person();
    Person.prototype.speak=function(){
    console.log("hello world");
    }
    p.speak();//hello world

    原型模式缺点:实例之间共享所有的原型属性和方法,有些个性化的属性无法体现。

    4. * 组合使用构造函数模式和原型模式

    这种组合是最常见的一种方式,用构造函数模式创建实例属性,原型模式定义公用的属性和方法。

    function Person(name,age)
    {
      this.name=name;
      this.age=age;
      this.friends=['lucy','kate']
    }
    Person.prototype={
      constructor:Person,
      sayName:function(){
      console.log("my name is "+this.name);
      }
    }
    var p1=new Person('Ken',16);
    p1.sayName();//my name is Ken
    var p2=new Person('Peter',20);
    p2.sayName();//my name is Peter
    p1.friends.push('Zhang');
    console.log(p1.friends);// ["lucy", "kate", "Zhang"]
    console.log(p2.friends);// ["lucy", "kate"]

    5.动态原型模式

    function Person(name,age)
    {
      this.name=name;
      this.age=age;
      if(typeof this.sayName!='function'){
          Person.prototype.sayName=function(){
          console.log("my name is "+this.name);
          }
      }
    }
    var p1=new Person('Ken',16);
    p1.sayName();//my name is Ken
    var p2=new Person('Peter',20);
    p2.sayName();//my name is Peter

    说明:不必检查原型中的每个属性和方法,只要检查其中一个即可;

    不能使用对象字面量方法重写原型。

  • 相关阅读:
    atitit 提升数据库死锁处理总结
    CoreJava_线程并发(堵塞队列):在某个目录下搜索含有某keyword的文件
    HDU 4389——X mod f(x)(数位DP)
    POJ 1182 (经典食物链 /并查集扩展)
    【iOS-Android开发对照】 之 APP入口
    《Pro Android Graphics》读书笔记之第四节
    Android多个Module统一配置相同jar或库的版本号
    教你上传代码到码云(与github一样)
    解决本地项目推送到码云(github),上提示:failed to push some refs to ...
    android adb常用指令
  • 原文地址:https://www.cnblogs.com/janes/p/3858655.html
Copyright © 2011-2022 走看看