JS - 2023-02-28笔记总结

79 阅读2分钟

手写instanceof

出题目的

  • 考察原型链的理解

知识点

instanceof

  • instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
  • 可以判断继承关系,只要是在同一条原型链上,就可以返回true

参考答案

while (true) {
  if (obj1Proto === null) {
  	return false;
  } else if (obj1Proto === obj2Prototype) {
  	return true;
  }

  obj1Prto = obj1Proto.__proto__;
}

this不同场景,如何取值?

this 易混场景

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

测试题

// 题目1
 let obj = {
  x: 123,
  show() {
    setTimeout(() => {
      console.log(this.x);
    }, 100);
  },
};
obj.show();
obj.show.call({x:100})

// 题目2
let obj = {
  fn: () => {
    console.log(this, 999);
  },
};

obj.fn();

演示代码

情况1:
    o 是 new 实例化来的,有单独的作用域
    class Obj {
      say = () => {
        console.log(this); // this -> Obj
      };
    }

    const o = new Obj();
    o.say();

    const oBtn = document.getElementById("btn");
    oBtn.onclick = function () {
      console.log(this);
    };

手写bind函数

知识点

  • Function.prototype.myBind
  • Array.prototype.slice.call()
  • array.shift()

演示代码

<!DOCTYPE html>
<html>
  <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>@说人话的前端 - bilibili</title>
  </head>
  <body></body>
  <script>
    function fn(a, b, c, d) {
      console.log(this);
      console.log(a, b, c, d);

      return "this is return";
    }

    // const cb = fn.bind({ x: 100 }, 1, 2, 3);
    // console.log(cb());

    // 手写bind
    Function.prototype.myBind = function () {
      const fn = this;

      const arg = Array.prototype.slice.call(arguments);
      const _this = arg.shift();

      return function () {
        return fn.apply(_this, arg);
      };
    };

    const cb = fn.myBind({ x: 300 }, 1, 2, 3, 4);
    console.log(cb());
  </script>
</html>

谈谈闭包和闭包使用场景

什么是闭包

概念:闭包是作用域的一种特殊应用

触发闭包的情况

1、函数当做返回值被返回

2、函数当做参数被传递

3、自执行匿名函数

闭包的应用

1、隐藏变量

2、解决 for i 的问题

作用域

全局作用域、局部作用域

自由变量

不在自己作用域里的变量,就是自由变量

自由变量的值:在函数定义的地方向上层作用域查找。与函数调用位置无关

演示代码

<!DOCTYPE html>
<html>
  <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>@说人话的前端 - bilibili</title>
  </head>
  <body></body>
  <script>
    // 情况1:函数当做返回值被返回
    // function fn() {
    //   const a = 1;
    //   return function () {
    //     console.log(a);
    //   };
    // }
    // const a = 5;
    // const cb = fn();
    // cb();

    // 情况2:函数当做参数传递
    // function fn(cb) {
    //   const a = 100;
    //   cb();
    // }

    // const a = 500;
    // fn(function () {
    //   console.log(a);
    // });

    // 情况3:自执行匿名函数
    (function (index) {
      console.log(index);
    })(10);
  </script>
</html>

<!DOCTYPE html>
<html>
  <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>@说人话的前端 - bilibili</title>
  </head>
  <body>
    <button>0</button>
    <button>1</button>
    <button>2</button>
    <button>3</button>
    <button>4</button>
  </body>
  <script>
    const aBtn = document.getElementsByTagName("button");

    // for (var i = 0; i < aBtn.length; i++) {
    //   (function (index) {
    //     aBtn[i].onclick = function () {
    //       console.log(index);
    //     };
    //   })(i);
    // }
    for (let i = 0; i < aBtn.length; i++) {
      aBtn[i].onclick = function () {
        console.log(i);
      };
    }
  </script>
</html>

<!DOCTYPE html>
<html>
  <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>@说人话的前端 - bilibili</title>
  </head>
  <body></body>
  <script>
    // 隐藏变量
    function fn() {
      const data = {};

      return {
        set: function (key, val) {
          data[key] = val;
        },
        get: function (val) {
          return data[val];
        },
      };
    }

    const json = fn();
    json.set("age", 18);
    console.log(json.get("age"));
  </script>
</html>

请描述event loop的机制

Javascr是如何执行的?

  • 自上而下,从左到右一行一行执行
  • 如果有一行报错,后面的代码不执行
  • 先执行同步代码,再执行异步代码(setTimeout、Ajax

Event Loop 过程

  1. 同步代码,一行一行放在 Call Stack 中执行
  2. 遇到异步,会先“记录”下代码,等待执行时机(setTimeout、Ajax)。时机到了,将之前“记录”的代码放入 Callback Queue
  3. 当 Call Stack 为空(同步代码执行完),Event Loop 开始工作
  4. Event Loop 轮询查找 Callback Queue 中是否有可执行的代码。如果有,将代码移动到 Call Stack 中执行
  5. Event Loop 如果没有找到可以执行代码,则会继续轮询查找

![image.png](p6-juejin.byteimg.com/tos-cn-i-k3…?

演示代码

<!DOCTYPE html>
<html>
  <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>@说人话的前端 - bilibili</title>
  </head>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    /* 盒子模型=200+20+10
    */
    div {
      width: 500px;
      height: 200px;
      padding: 10px;
      border: 5px solid red;
      background-color: #ccc;
      box-sizing: content-box;
    }
  </style>
  <body>
    <div id="div1">说人话的前端 - bilibili</div>
    <script>
      let w = document.getElementById("div1").offsetWidth;
      console.log(w);
    </script>
  </body>
</html>