相信從事前端開發的小夥伴對instanceof和new關鍵字應該不陌生,isntanceof主要用來判斷類型,返回布爾值,new主要用來實例化類函數,接下來咱們來實現一下這兩個方法。javascript
// 聲明變量
const str = '123'
const num = 123
// 打印
console.log(str instanceof String) // true
console.log(num instanceof Number) // true
複製代碼
能夠看出instanceof主體分左右兩邊,左邊是待校驗類型,右邊是目標類型,下面咱們來實現一個:前端
// 主函數
function newInstanceof(current, target) {
// 獲取左邊的__proto__
let left = current.__proto__
// 獲取右邊的prototype
let right = target.prototype
// while循環查找左邊的__proto__
while(left) {
if(left === right) {
return true
}
left = left.__proto__
}
return false
}
// 測試
const res1 = newInstanceof('123', String)
console.log(res1) // true
const res2 = newInstanceof(123, Number)
console.log(res2) // true
複製代碼
這裏咱們主要要說明的是__proto__和prototype,__proto__指向構造該對象的構造函數的原型,prototype指的是包含全部實例共享的屬性和方法,咱們一般稱之爲原型對象。全部對象都有__proto__屬性,而prototype只有函數對象纔有。java
function Foo(value) {
this.value = value
return value
}
Foo.prototype.set = function() {
console.log(this.value)
}
const res = new Foo('init')
res.set() // init
res.value // init
複製代碼
以上代碼能夠看出new以後的對象具有實例化對象的prototype全部屬性和私有屬性,這裏咱們再改造一下Foo函數markdown
function Foo(value) {
this.value = value
return {
obj: 'return object'
}
}
const res = new Foo('init')
console.log(res) // {obj: 'return object'}
複製代碼
兩個Foo函數,返回普通類型,實例化以後獲得的是繼承得對象;返回引用類型,實例化以後獲得的是該類型,基於這個特性咱們來實現一下函數
function newInstanceof(fn,...args) {
// 建立新對象,賦值fn得prototype
const obj = Object.create(fn.prototype)
// 改變fn的this指向,從新指向obj
const res = fn.call(obj,...args)
return res instanceof Object ? res : obj
}
// 測試返回引用類型
function Foo(value) {
this.value = value
return {
obj: value
}
}
const res = newInstanceof(Foo, 'init')
res.obj // init
// 測試返回普通類型
function Bar(value) {
this.value = value
return this.value
}
const resBar = newInstanceof(Bar, 'bar')
resBar.value // bar
複製代碼
至此instanceof和new的運做機制已經實現完成,有問題歡迎在評論中指出。測試