JS必会的面试题2

80 阅读1分钟

手写instanceof

instanceof

  • instanceof 运算符用于检测构造函数的prototype属性 是否在某个实例对象的原型链上
  • 可以判断继承关系 只要是在同一条原型链上 就返回true
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        class Proson {
            constructor(name, age) {
                this.name = name
                this.age = age
            }
        }
        class Student extends Proson {
            constructor(name, age, sex) {
                super(name, age)
                this.sex = sex
            }
        }
        let zhangsan = new Student("zhangsan", 18, "男")
        function myInstanceof(obj1, obj2) {
            let objproto = obj1.__proto__//记录传进来的实例对象的__proto__属性
            while (true) {
                // 如果 传进来的实例对象的__proto__属性 === null 就证明不在一个原型链上直接返回false
                if (objproto === null) {
                    return false
                } else if (objproto === obj2.prototype) { //如果实例对象的__proto__属性 === 构造函数的prototype属性直接返回true
                    return true
                }
                // 继续向上找 每次循环完把新的__proto__属性赋值给变量
                objproto = objproto.__proto__
            }
        }
        console.log(myInstanceof(zhangsan, Object));
        console.log(myInstanceof(zhangsan,Proson));
        console.log(zhangsan);
    </script>
</body>

</html>

this不同场景如何取值

this易混场景

  • 普通函数下的this
  • call applay bind中的this
  • 定时器中的this
  • 箭头函数中的this

场景1 普通函数下的this

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        // 普通函数的this 
        // 非严格模式下this指向是window
        // 严格模式下this指向是undefined
        // "use strict"
        function a(){
            console.log(this);
        }
        a()
        
    </script>
</body>
</html>

场景2 call apply bind中的this

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        // call apply bind this指向
        //情况1 this===>window
        function a (){
            console.log(this);
        }
       //a.call()//window
       //a.call(undefined)//window
       //a.call(null)//window
       //情况2 传什么this就指向什么
        let fn =  a.bind({x:101})
        fn()
        a.apply("")
        a.call(123)
    </script>
</body>
</html>

场景3 定时器中的this

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        // 情况1 settimeout + function this===>window
        // 情况2 settimeout + 箭头函数 this===>上层作用域的this
        setTimeout(function(){
            console.log(this);
        },100)
        function fn(){
            setTimeout(function(){
                console.log(this);
            },100)
        }
       fn.call({x:100})//window

        // 情况2 指向上层作用域的this
        class Obj{
            fn(){
                setTimeout(()=>{
                    console.log(this);
                },100)
            }
        }
        let o = new Obj()
        o.fn()

        function fn(){
            setTimeout(()=>{
                console.log(this);
            })
        }
        fn.call({x:200})
    </script>
</body>
</html>

场景4 箭头函数中的this

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button>test</button>
    <script>
        // 箭头函数中的this
        //情况1:有function作用域的this指向上层this
        //情况2:没有function作用域的this指向window
        //情况1
        class Obj{
            say = ()=>{
                console.log(this);
            }
        }
        let obj = new Obj()
        obj.say()//指向obj类
        //情况2 
        const obj2 = {
            say:()=>{
                console.log(this);
            }
        }
        obj2.say()//指向window
        const btn = document.querySelector("button")
        btn.onclick = ()=>{
            console.log(this);//没有function作用域 所以指向window
        }
        btn.onclick = function(){
            console.log(this);//有function作用域所以指向button按钮
        }
    </script>
</body>
</html>

面试题

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        const fn = {
            x:123,
            show(){
                setTimeout(()=>{ //箭头函数的this指向上层
                    console.log(this.x);
                },100)
            }
        }
        fn.show()//123
        fn.show.call({x:100})//100
    </script>
</body>
</html>

手写bind函数

知识点

  • function.prototype.mybind
  • Array.prototype.slice.call()
  • array.sshift()
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=\, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        function fn(a, b, c) {
            console.log(this);
            console.log(a, b, c);
            return "this is fun"
        }
        // let cc = fn.bind({x:100})
        // console.log(cc());
        //手写bind
        Function.prototype.mybind =function(){
            let fn = this
            let arg = Array.prototype.slice.call(arguments)
            let _this = arg.shift()
            return function(){
                return fn.apply(_this,arg)
            }
        }
        const cb = fn.mybind({x:200,y:200},1,2,3)
        cb()
        console.log(cb());
    </script>
</body>

</html>