關於new命令

前言

JS中有一種說法,叫作一切皆爲對象。對象是什麼呢?大話來說,對象是一種容器,裏面封裝了屬性和方法。在天天編程中,最基本的事情也是頻繁的乾的事情就是建立一個對象,而後使用它幹各類各樣的事情。建立對象的方法有構造函數建立、語法糖建立、還有new命令建立。固然,本文的標題已經代表此次的主角是new關鍵字了。面試

new的基本用法

new命令的做用,就是執行構造函數,返回一個實例對象。編程

ps:若是忘了使用new命令,構造函數就變成了普通函數,並不會生成實例對象。segmentfault

// 一、不帶參數狀況
var Vehicle = function () {
  this.price = 1000;
};

var v = new Vehicle();
v.price // 1000

// 二、帶參數狀況
var Vehicle = function (p) {
  this.price = p;
};

var v = new Vehicle(500);

固然,爲了保證構造函數必須與new命令一塊兒使用兩種方法。數組

方法一:構造函數內部使用嚴格模式,即第一行加上use strict。這樣的話,一旦忘了使用new命令,直接調用構造函數就會報錯。app

function Fubar(foo, bar){
  'use strict';
  this._foo = foo;
  this._bar = bar;
}

Fubar()
// TypeError: Cannot set property '_foo' of undefined

方法二:構造函數內部判斷是否使用new命令,若是發現沒有使用,則直接返回一個實例對象。函數

function Fubar(foo, bar) {
  if (!(this instanceof Fubar)) {
    return new Fubar(foo, bar);
  }

  this._foo = foo;
  this._bar = bar;
}

Fubar(1, 2)._foo // 1
(new Fubar(1, 2))._foo // 1

new原理詳解

面試的時候經常會問道,使用new命令時,會發生什麼。post

一、建立一個空對象,做爲將要返回的對象實例。this

二、將這個空對象的原型,指向構造函數的prototype屬性。url

三、將這個空對象賦值給函數內部的this關鍵字。prototype

四、開始執行構造函數內部的代碼。

從上面步驟能夠看出,其構造函數內部,經過this指的就是新生對象。
若是你對this不是很清楚,能夠看個人另外一篇文章
關於this、call、applay和bind

注意:若是構造函數內部有return語句,並且return後面跟着一個對象,new命令會返回return語句指定的對象;不然,就會無論return語句,返回this對象。

例子1

var Vehicle = function () {
  this.price = 1000;
  return 1000;
};

(new Vehicle()) === 1000
// false

例子2

var Vehicle = function (){
  this.price = 1000;
  return { price: 2000 };
};

(new Vehicle()).price
// 2000

另外一方面,若是對普通函數(內部沒有this關鍵字的函數)使用new命令,則會返回一個空對象。

function getMessage() {
  return 'this is a message';
}

var msg = new getMessage();

msg // {}
typeof msg // "object"

new關鍵字的內部流程

function _new(/* 構造函數 */ constructor, /* 構造函數參數 */ params) {
  // 將 arguments 對象轉爲數組
  var args = [].slice.call(arguments);
  // 取出構造函數
  var constructor = args.shift();
  // 建立一個空對象,繼承構造函數的 prototype 屬性
  var context = Object.create(constructor.prototype);
  // 執行構造函數
  var result = constructor.apply(context, args);
  // 若是返回結果是對象,就直接返回,不然返回 context 對象
  return (typeof result === 'object' && result != null) ? result : context;
}

// 實例
var actor = _new(Person, '張三', 28);
相關文章
相關標籤/搜索