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

2015-04-05 13:58:00  浏览:1700  作者:管理员

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

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);

 

评论区

共 0 条评论
  • 这篇文章还没有收到评论,赶紧来抢沙发吧~

【随机新闻】

返回顶部