转载

一道有意思的笔试题引发的对于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的内容截图:

一道有意思的笔试题引发的对于new操作符的思考

我们可以清楚看到,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);

一道有意思的笔试题引发的对于new操作符的思考

观察输出的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);
正文到此结束
Loading...