Fe-interview: Day11:写出执行结果,并解释原因

Created on 22 Jun 2020  ·  6Comments  ·  Source: lgwebdream/FE-Interview

function f(){
      return f;
 }
console.log(new f() instanceof f);
// 写出执行结果,并解释原因

每日一题会在下午四点在交流群集中讨论,五点小程序中更新答案
欢迎大家在下方发表自己的优质见解
二维码加载失败可点击 小程序二维码

扫描下方二维码,收藏关注,及时获取答案以及详细解析,同时可解锁800+道前端面试题。

Most helpful comment

new f() 返回的是 f 这个函数对象。
而 o instanceOf O的实现原理是,检测o的原型链上有没有O.prototype 即 o.__proto__ == O.prototype || o.__proto__.__proto__ == O.prototype。调试可以看出,两者并不相同。

All 6 comments

答案
false

解析
a instanceof b 用于检测a是不是b的实例。如果题目f中没有return f,则答案明显为true;而在本题中new f()其返回的结果为f的函数对象,其并不是f的一个实例。

function f(){}
 console.log(new f() instanceof f);
// 答案:true

new f() 返回的是 f 这个函数对象。
而 o instanceOf O的实现原理是,检测o的原型链上有没有O.prototype 即 o.__proto__ == O.prototype || o.__proto__.__proto__ == O.prototype。调试可以看出,两者并不相同。

而 o instanceOf O的实现原理是,检测o的原型链上有没有O.prototype 即 o.proto == O.prototype || o.proto.proto == O.prototype。调试可以看出,两者并不相同。

instanceOf的实现原理原来是这样

如果函数返回值是Object类型,那么new操作符会返回这个Object类型的值。如果返回值不是Object类型(不写return就是返回undefined),那么new操作符会返回该函数的一个实例

先来看下 new 关键字做了什么:

function mockNew() {
  let Con = [].shift.call(arguments)
  let o = {}

  let res = Con.apply(o, arguments)
  if(res instanceof Object) return res

  o.__proto__ = Con.prototype
  return o
}

上面的函数 mockNew 模拟了 new 关键字创建一个实例的过程。首先拿到传入参数的构造函数,创建了一个命名为 o 的对象;执行构造函数 Con,将其 this 绑定为 o;最关键的在于,会检测构造函数返回的结果是不是 Object 对象的实例,如果是的话会返回构造函数的执行结果,否则返回创建的 o

再来看下 instanceof 操作符做了什么:

function mockInstance(proto, parent) {
    if(proto === null) return false
    while(proto) {
        if(parent.prototype === proto) return true
        else proto = proto.__proto__
    }
    return false
}

上面的函数表明了 instanceof 的原理,沿着原型链一层一层往上找,直到原型匹配或者原型为 null 为止。

配合题目来理解:

function f() {
      return f; // 函数 f 继承自对象,所以 new 之后会返回函数本身
 }
console.log(new f() instanceof f); // 函数的上层原型链是 native code,native code 上层的原型链是 Object,不和 f.prototype 相等,所以返回值为 false

如何把 URL 里的 queryString 转化成一个对象?如 ?a=b&c=1,转成 { a: 'b', c: 1 },我们来介绍 2 种方式。

第一种使用正则:

var url = 'https://www.baidu.com/s?wd=%E6%B5%8B%E8%AF%95&rs&rsv_spt=1&rsv_spt=2&rsv_iqid=0xec504f1800025d7f&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&rqlang=cn&tn=baiduhome_pg&rsv_enter=1&rsv_dl=tb&oq=test&rsv_btype=t&inputT=2899&rsv_t=e5aaY3xRbIqZc93Af9wRS9O36UFIWlR2BVTmZTGoNcnBP%2BJGFg19WmoA%2B8aIBIUw9lU2&rsv_sug3=18&rsv_sug1=13&rsv_sug7=100&rsv_pq=afe6a1b00001e182&rsv_sug2=0&rsv_sug4=3654'
var reg = /[?|&]([^&=]+)=?([^&]*)/g
var res = url.matchAll(reg)
var obj = {}

for(let item of res) {
    let k = item[1]
    let v = decodeURIComponent(item[2]) || true
    if(!isNaN(v) && v !== true) v = +v

    let valueInObj = obj[k]
    if(!valueInObj) obj[k] = v
    else {
        if(Array.isArray(valueInObj)) valueInObj.push(v)
        else {
            obj[k] = [valueInObj, v]
        }
    }
}
console.log(obj)

第二种使用原生的 api URL

var anotherUrl = new URL(url)
var anotherObj = {}
for(let [k, v] of anotherUrl.searchParams.entries()) {
    v = v || true
    if(v !== true && !isNaN(v)) v = +v
    if(!anotherObj[k]) {
        anotherObj[k] = v
    } else {
        anotherObj[k] = Array.isArray(anotherObj[k]) ? [...anotherObj[k], v] : [anotherObj[k], v]
    }
}
console.log(anotherObj)
Was this page helpful?
0 / 5 - 0 ratings