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
  • 相关阅读:
    97. Interleaving String
    96. Unique Binary Search Trees
    95. Unique Binary Search Trees II
    94. Binary Tree Inorder Traversal
    odoo many2many字段 指定打开的form视图
    docker sentry 配置文件位置
    postgres 计算时差
    postgres 字符操作补位,字符切割
    postgres判断字符串是否为时间,数字
    odoo fields_view_get
  • 原文地址:https://www.cnblogs.com/web-record/p/10299605.html
Copyright © 2011-2022 走看看