zoukankan      html  css  js  c++  java
  • 一道有意思的笔试题引发的对于new操作符的思考

      楼主比较喜欢看一些很短但很有意思的题目,无意间又瞥到了一题,大家不妨可以一试。(原题链接猛戳这里

    function Fn1() {
      this.name = 'peter';
      return {
        name: 'jack'
      };
    
    }
    
    function Fn2() {
      this.name = 'peter';
      return 'jack';
    }
    
    var obj1 = new Fn1();
    var obj2 = new Fn2();
    console.log(obj1.name, obj2.name);

      或许你经常写面向对象编程的代码,也熟悉以上代码中this的用法甚至是prototype或者原型链,但是还是无法解释上面代码的输出,这时我们不得不承认对new的了解还不是很透彻。

      先看一段普通的使用new操作符创建对象的代码:

    function Person(a, b) {
      this.name = a;
      this.age = b;
    }
    
    Person.prototype.show = function() {
      console.log(this.name, this.age);
    };
    
    var p = new Person('hanzichi', 10);
    console.log(p);

      将console的内容截图:

      我们可以清楚看到,p是一个对象,并且拥有构造函数Person中创建的name和age属性,还有个__proto__属性(这货太特殊,反正不在p的hasOwnProperty内!),其值为构造函数的prototype属性值。

      其实new操作符创建对象可以分为四个步骤:

    1. 创建一个空对象
    2. 将所创建对象的__proto__属性值设成构造函数的prototype属性值
    3. 执行构造函数中的代码,构造函数中的this指向该对象
    4. 返回该对象(除非构造函数中返回一个对象)

    用代码表示如下:

    function Person(a, b) {
      this.name = a;
      this.age = b;
    }
    
    Person.prototype.show = function() {
      console.log(this.name, this.age);
    };
    
    // var p = new Person('hanzichi', 10);
    var p = {};
    p.__proto__ = Person.prototype;
    Person.call(p, 'hanzichi', 10);
    
    console.log(p);

      观察输出的p,我们看到获取的对象p和通过new操作符获取的对象属性以及属性值一致,甚至连p.__proto__通过hasOwnProperty都无法检测到!

      通过以上的介绍,我们基本就可以解答本文开头的那个问题了,其实就是构造函数里,如果返回一个非null的对象(包括数组),则将该对象值赋值给新建的对象,其实上面的实例代码还少了一个是否返回对象的判断,整理后应该是:

    function Person(a, b) {
      this.name = a;
      this.age = b;
      return {
        name: 'zichi'
      };
    }
    
    Person.prototype.show = function() {
      console.log(this.name, this.age);
    };
    
    function init() {
      var p = {};
      p.__proto__ = Person.prototype;
      var temp = Person.call(p, 'hanzichi', 10);
      if(temp !== null && typeof temp === 'object')
        return temp;
      return p;
    }
    
    var p = init();
    console.log(p);

  • 相关阅读:
    影响CSS的margin合并的几个属性
    Mouse w/o Borders实现两台主机共用一套键鼠方法及问题处理
    隐藏"Input"标签默认样式
    如何快速开发网站?
    如何让Web.xml变得简洁?
    关于中文处理方面的研究
    Hello,World 百态
    UI开发的终极解决方案
    构建网络爬虫?so easy
    MDA数据校验规则定义
  • 原文地址:https://www.cnblogs.com/lessfish/p/4392944.html
Copyright © 2011-2022 走看看