zoukankan      html  css  js  c++  java
  • JS构造函数new的过程

    造函数其实和普通函数本质上并无区别,唯一的区别有两个:

    函数首字母大写,这个区别只是约定俗成的,便于区分。你实在要小写定义构造函数也完全没问题,所以这个区别可以忽略。
    构造函数的调用需要用new操作符,而普通函数的调用又分很多种,但是都不会用到new操作符。所以,构造函数和普通函数的区别就在这个new操作符里,现在让我们来好好研究一下这个new操作符。

    用new操作符创建对象时发生的事情:

    (1)创建一个新对象;

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

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

    (4)返回新对象;

    通过new操作符后跟构造函数的方式创建的对象(实例),这个对象有一个constructor(构造函数)属性,该属性指向构造函数Person。

    创建的对象,毫无疑问是Person的实例,同时也是Object的实例;所有对象皆继承自Object。

    构造函数是定义在Global对象中的,在浏览器中,即为window对象。

    注意:原本的构造函数是window对象的方法,如果不用new操作符而直接调用,那么构造函数的执行对象就 是window,即this指向了window。现在用new操作符后,this就指向了新生成的对象。理解这一步至关重要。
    执行构造函数中的代码,看代码:

    function Person(){
      this.name = "Tiny Colder";
      var age = 22;
      window.age = 22;
    }
    var p = new Person();
    alert(p.name)//Tiny Colder;
    alert(p.age)//undefined;
    alert(window.age)//22;

    当用new操作符创建对象时,先创建了一个对象实例,然后执行代码。所以还在纠结,什么时候构造函数定义的属性会继承给实例对象的,都可以这么来看:

    var p = new Object();
    p.name = "Tiny Colder";

    这是普通的创建对象,然后给对象添加属性的方法。如果每创建一个对象,都需要这么几行代码,无疑是糟糕的。这个需求就正好跟这一点对应:new操作符,自动执行构造函数里的代码。如此我们便可以省掉添加属性时重复冗余的代码。那么这些属性时如何添加到新生成的对象里的呢?

    第二个步骤里已经说了:将构造函数的执行对象赋给新生成的这个实例。再结合上一段里说的,自动执行构造函数里的this.name = "Tiny Colder";时,就相当于是执行p.name = "Tiny Colder";而构造函数里的var age = 22;语句,会执行但是对新生成的对象并无影响。window.age = 22;语句,会执行,且会给window对象添加一个属性。alert为证。
    或许到这里,你已经理解了new操作符的前三步了,重要的三步。但是这个函数是如何返回对象的呢?我们并没有看到有任何跟return相关的语句。这就是new操作符的最后一步:返回新生成的对象。
    如果被调用的函数没有显式的 return 表达式(仅限于返回对象),则隐式的会返回 this 对象 - 也就是新创建的对象。
    现在来看一下这个代码:
    function Person(){
          this.name = "Tiny Colder";
          return {};
    }
    var p = new Person();
    alert(p.name)//undefined;

    一个对象就这么被创建出来了。
    实际上,

    var p = new Person();


    var p = new Object();
    Person.apply(p);
    是一样的效果。

    构造函数也是函数

    任何函数,只要通过new操作符来调用,那么它就可以作为构造函数;任何函数,如果不通过new操作符来调用,那它与普通函数并无区别。

    (1)当做构造函数调用

    var person = new Person("CC",23);

    (2)当做普通函数使用

    Person("CC",23);    //添加到window对象
    console.log(window.name);    //"CC"
    console.log(window.age);    //23

    (3)在另一个对象的作用域中调用

    var person = new Object();
    Person.call(person,"CC",23);
    console.log(person.name);    //"CC"
    console.log(person.age);    //23

    构造函数的问题

    使用构造函数的主要问题,就是每个方法都要在每个实例上重新创建一次。

    var person1 = new Person("CC",23);
    var person2 = new Person("VV",32);

    两个实例都有sayName()方法,但是两个方法不是同一Function的实例,也就是说,两个实例上的同名函数是不相等的。

    console.log(person1.sayName == person2.sayName);    //false
  • 相关阅读:
    Asp.net并发请求导致的数据重复插入问题
    记一次完整的asp.net-mvc页面优化过程
    设计完美的策略模式,消除If-else
    EF|CodeFirst数据并发管理
    mongo upsert
    js回调函数传参
    使用poi时,两个环境下,一个错误一直正常
    jna笔记1
    springboot集成rabbitmq测试
    一个方法让你了解js中的细节
  • 原文地址:https://www.cnblogs.com/web-record/p/10299605.html
Copyright © 2011-2022 走看看