zoukankan      html  css  js  c++  java
  • 构造函数

    构造函数就是初始化一个实例对象,对象的prototype属性是继承一个实例对象

    下面两个例子:

     1 function creatPerson(name,age,job){
     2     //工厂模式创建对象
     3     var o=new Object();
     4     o.name=name;
     5     o.age=age;
     6     o.job=job;
     7     o.sayName=function(){
     8         alert(this.name);
     9     };
    10     return o;
    11 }
    12 var person1=creatPerson('LiMing',29,'Doctor');
    13 var person1=creatPerson('Greg',17,'Teacher');
     1 function Person(name,age,job){
     2     //构造函数模式创建对象
     3     var o=new Object();
     4     this.name=name;
     5     this.age=age;
     6     this.job=job;
     7     this.sayName=function(){
     8         alert(this.name);
     9     };
    10 }
    11 var person1=Person('LiMing',29,'Doctor');
    12 var person1=Person('Greg',17,'Teacher');

    Person()中的代码除了与creatPerson()中相同的部分外,还存在以下不同之处:

    1.没有显式地创建对象;

    2.直接将属性和方法赋给了this对象;

    3.没有return语句;

    4.函数名以大写字母开头。

    要创建Person新实例,,必须使用new操作符。

    使用new调用构造函数实际会经历以下四个步骤:

    1.创建一个新对象;

    2.将构造函数的作用域赋给新对象(this指向这个对象);

    3.执行构造函数中的代码(为这个新对象添加属性);

    4.返回新对象(返回this)。

    Person()中的两个实例person1和person 2都有一个constructor(构造函数)属性,该属性指向Person:

    alert(person1.constructor==Person);   //true
    alert(person2.constructor==Person);   //true

     对象的constructor属性最初是用来表示对象类型的,但要检测对象类型,还是用instanceof操作符。

    我们在这个例子中创建的所有对象既是Object的实例,同时也是Person的实例:

    alert(person1 instanceof Object);   //true
    alert(person1 instanceof Person);   //true
    alert(person2 instanceof Object);   //true
    alert(person2 instanceof Person);   //true

    1.将构造函数当做函数

    构造函数与其他函数的唯一区别,就在于他们的调用方式不同。

    不过,构造函数毕竟也是函数,不存在定义构造函数的特殊语法。

    任何函数,只要通过new操作符来调用,那它就可以作为构造函数;而任何函数,如果不通过new操作符调用,那它跟普通函数也没什么两样。

    //当作构造函数使用
    var person=new Person('LiMing',29,'Doctor');
    person.sayName();  //LiMing
    
    //作为普通函数使用
    Person('LiMing',29,'Doctor');  //添加到window
    window.sayName();  //在全局作用域 中调用一个函数时,this对象总是指向Global对象(在浏览器中就是全局对象)
    
    //在另一个对象的作用域中调用
    var o=new Object();
    //可以使用call()(或者apply())在某个特殊对象的作用域中调用Person()函数
    Person.call(o,'LiMing',29,'Doctor');  
    o.sayName();

    2.构造函数的问题

    构造函数模式虽然方便好用,但使用构造函数还有一个主要问题,就是每个方法都要在每个实例上重新创建一遍。

    在前面的例子中,person1和person2都有一个名为sayName()的方法,但那两个方法不是同一个Function的实例。

    此时的构造函数相当于:

     1 function Person(name,age,job){
     2     //构造函数模式创建对象
     3     var o=new Object();
     4     this.name=name;
     5     this.age=age;
     6     this.job=job;
     7     this.sayName=new Function(alert(this.name)); 
    10 }
    alert(person1.sayName == person2.sayName);    //false

    然而,创建两个完成同样任务的Function实例的确没有必要;况且有this对象在,根本不用在执行代码前就把函数绑定到特定对象上面。因此,可以通过把函数定义转移到构造函数外部来解决这个问题。

     1 function Person(name,age,job){
     2     //构造函数模式创建对象
     3     var o=new Object();
     4     this.name=name;
     5     this.age=age;
     6     this.job=job;
     7     this.sayName=sayName; 
     8 }
     9 
    10 function sayName(){
    11     alert(this.name);
    12 }
    13 
    14 var person1=Person('LiMing',29,'Doctor');
    15 var person2=Person('Greg',17,'Teacher');

    这样,sayName()函数就成为了全局函数,Person()函数中的sayName就是一个指向函数sayName()的指针,person1,person2对象就共享了在全局作用域中定义的同一个sayName()函数。

    那么新问题又来了:如果对象需要定义很多方法,那么就要定义很多全局函数,于是这个自定义的引用类型就毫无封装性可言了。

    这个问题可以通过原型模式来解决......

    参考《JavaScript高级程序设计》第三版 p144页

  • 相关阅读:
    虹软人脸识别在 linux中so文件加载不到的问题
    tomcat 控制台乱码问题
    sourceTree git 空目录从远程仓库克隆代码出现warning: templates not found
    springboot项目更改代码后实时刷新问题
    spring 3.0 整合redis
    随笔
    Centos 7 安装 FFmpeg
    Postgresql 查看当前数据库所有的触发器
    oracle只导出触发器
    oracle 批量删除触发器
  • 原文地址:https://www.cnblogs.com/lailailee/p/7446742.html
Copyright © 2011-2022 走看看