Maybe you and I have never met, but we may not have met. I am a head fish

Asked hemp

I believe my friends have been asked to realize XXX by hand more than once in the interview, and batehead fish has also been asked similar questions for n times. There is one topic which has profound reflection, instanceof implementation principle. In this article, I would like to try to realize XXX in at least three ways with everyone.

Bighead handwriting realization Warehouse (350 STAR), you need handwriting, welcome to click to have a look

Github.com/qianlongo/f…

Usage review

The instanceof operator is used to check whether the constructor’s prototype property appears on the prototype chain of an instance object. On the MDN

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
const auto = new Car('Honda'.'Accord'.1998);

console.log(auto instanceof Car);
// expected output: true

console.log(auto instanceof Object);
// expected output: true

Copy the code

Prototype chain Review

Prototype and prototype chain are the most important knowledge points to implement instanceof. Here is a brief review and recommend two well-written articles.

  • You need to know about prototypes and prototype chains
  • This is probably the best nuggets talk about “prototype chain”, the most easy to understand, with exercises

See figure:

1.F is an instance object of Fo, and it will have a __proto__ attribute pointing to the prototype of Fo2.Fo inherits from Foo, whose prototype is an instance of Foo, and has a __proto__ attribute pointing to Foo's prototype3.Foo inherits from the top-level objectObjectAnd the prototype isObjectWill have a __proto__ attribute to point toObject.prototype
4. ObjectPrototype is already the top-level object to which its __proto__ attribute pointsnull

Copy the code

Code sample

const Foo = function (name, sex) {
  this.name = name
  this.sex = sex
}
Foo.prototype.showName = function () {
  console.log(this.name)
}

const Fo = function (name) {
  Foo.call(this, name)
}
Fo.prototype = Object.create(Foo.prototype)

const f = new Fo('Front End Bighead')

f.showName() // Front end bighead fish

Copy the code

Three implementations

To implement instanceof, you essentially just iterate through the prototype chain of the instance Object, looking up one by one to see if there is any prototype equal to Fn’s prototype, until the topmost Object is not found, then return false, otherwise return true

Key points:

  1. The constructorThe prototype of Fn
  2. The prototype chain of instance objects

Recursive implementation (Approach 1)


/ * * * *@param {*} Obj instance object *@param {*} Func constructor *@returns true false
 */
const instanceOf1 = (obj, func) = > {
  // Must be an object or a function
  if(! (obj && ['object'.'function'].includes(typeof obj))) {
    return false
  }

  let proto = Object.getPrototypeOf(obj)

  if (proto === func.prototype) {
    return true
  } else if (proto === null) {
    return false
  } else {
    return instanceOf1(proto, func)
  }
}

/ / test
let Fn = function () {}let p1 = new Fn()

console.log(instanceOf1({}, Object)) // true
console.log(instanceOf1(p1, Fn)) // true
console.log(instanceOf1({}, Fn)) // false
console.log(instanceOf1(null, Fn)) // false
console.log(instanceOf1(1, Fn)) // false
Copy the code

Traversal implementation (Approach 2)

/ * * * *@param {*} Obj instance object *@param {*} Func constructor *@returns true false
 */
const instanceOf2 = (obj, func) = > {
  // Must be an object or a function
  if(! (obj && ['object'.'function'].includes(typeof obj))) {
    return false
  }

  let proto = obj

  while (proto = Object.getPrototypeOf(proto)) {
    if (proto === func.prototype) {
      return true}}return false
}

/ / test
let Fn = function () {}let p1 = new Fn()

console.log(instanceOf2({}, Object)) // true
console.log(instanceOf2(p1, Fn)) // true
console.log(instanceOf2({}, Fn)) // false
console.log(instanceOf2(null, Fn)) // false
console.log(instanceOf2(1, Fn)) // false

Copy the code

Traversal implementation (Approach 3)

/ * * * *@param {*} Obj instance object *@param {*} Func constructor *@returns true false
 */
const instanceOf3 = (obj, func) = > {
  // Must be an object or a function
  if(! (obj && ['object'.'function'].includes(typeof obj))) {
    return false
  }

  let proto = Object.getPrototypeOf(obj)
  // Because there must be an end (topmost Object), it is not an infinite loop
  while (true) {
    if (proto === null) {
      return false
    } else if (proto === func.prototype) {
      return true
    } else {
      proto = Object.getPrototypeOf(proto)
    }
  }
}

/ / test
let Fn = function () {}let p1 = new Fn()

console.log(instanceOf3({}, Object)) // true
console.log(instanceOf3(p1, Fn)) // true
console.log(instanceOf3({}, Fn)) // false
console.log(instanceOf3(null, Fn)) // false
console.log(instanceOf3(1, Fn)) // false


Copy the code

The last

I hope I can share practical, basic and advanced knowledge points with you all the time.

I look forward to your attention in nuggets: front end bighead fish, you can also find me in the public number: front end bighead fish.