var Fn = {}
var fn = new Fn()
這個過程會執行如下步驟:
1.新創建一個空對象
var fn = new Object();
2.構造函數的顯示原型等於實例對象的隱式原型,實例對象的constructor屬性為構造函數的名稱
Fn.prototype = fn.__proto__
3.通過調用call、apply方法執行構造函數並改變this對象(綁定到實例對象上)
Fn.call(f)
4.如果沒有手動返回其他任何對象或返回值是基本類型(Number、String、Boolean)的值,會返回 this 指向的新對象,也就是實例,若返回值是引用類型(Object、Array、Function)的值,則實際返回值為這個引用類型。
var New =function(fn){ //1.新建空對象
var obj={}; //2.實例對象的__proto__等於構造函數的prototype
obj.__proto__=fn.prototype; //3. 將 arguments 對象轉為數組
var args = [].slice.call(arguments); //4.去除構造函數
args.shift(); //5. 通過調用call、apply方法執行構造函數並改變this對象
var result = fn.apply(obj, args); //6. 判斷返回值,如果是Object類型就直接返回,否則返回實例對象本身
if(Object.prototype.toString.call(result)=="[object Object]" ){ return result }else{ return obj; } } var Fun=function(sex){ this.name='hty'; this.sex=sex; } const fun=New(Fun,'123'); console.log(fun.name);//hty
console.log(fun.sex);//123
自己手寫實現一個簡單的new
function myNew (fun) { return function () { // 創建一個新對象且將其隱式原型指向構造函數原型
let obj = { __proto__ : fun.prototype } // 執行構造函數
fun.call(obj, ...arguments) // 返回該對象
return obj } } function person(name, age) { this.name = name this.age = age } let obj = myNew(person)('li', 18)
console.log(obj)
注意:
箭頭函數中沒有 [[Construct]] 方法,不能使用 new 調用,會報錯。除了箭頭函數之外的任何函數都可以new。
自己模擬面試想到的面試題
構造函數怎么調用的?(new)
為什么要用new來調用,而不是直接調用?
用new調用的時候,會新建一個空的實例對象,將構造函數的顯示原型等於實例的隱式原型,會將構造函數原型上的屬性和方法都繼承到實例對象中,會將this指向這個新實例對象,如果不用new調用的話就相當於是一個普通函數,this會指向window,也無法繼承構造函數的任何屬性。
想要系統了解更多知識推薦這個:https://www.cnblogs.com/echolun/p/10110839.html
https://developer.51cto.com/art/201807/578260.htm
Object.prototype.toString()
返回一個表示該對象的字符串
可以通過 toString()
來獲取每個對象的類型。為了每個對象都能通過 Object.prototype.toString()
來檢測,需要以 Function.prototype.call()
或者 Function.prototype.apply()
的形式來調用,傳遞要檢查的對象作為第一個參數,稱為 thisArg
。
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/toString