{"id":19451654,"url":"https://github.com/sunniejs/javascript-question","last_synced_at":"2025-02-25T09:26:30.252Z","repository":{"id":106263510,"uuid":"251191152","full_name":"sunniejs/javascript-question","owner":"sunniejs","description":"前端面试题 | Javascript 题 | CSS 题 | 前端届的3年高考5年模拟","archived":false,"fork":false,"pushed_at":"2020-07-02T10:05:10.000Z","size":1363,"stargazers_count":23,"open_issues_count":4,"forks_count":8,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-07T23:52:59.504Z","etag":null,"topics":["interview","interview-questions","javascript-questions"],"latest_commit_sha":null,"homepage":"https://sunniejs.github.io/javascript-question/","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sunniejs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-03-30T03:25:37.000Z","updated_at":"2024-09-26T17:21:24.000Z","dependencies_parsed_at":"2023-04-01T02:49:42.979Z","dependency_job_id":null,"html_url":"https://github.com/sunniejs/javascript-question","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunniejs%2Fjavascript-question","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunniejs%2Fjavascript-question/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunniejs%2Fjavascript-question/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sunniejs%2Fjavascript-question/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sunniejs","download_url":"https://codeload.github.com/sunniejs/javascript-question/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240639165,"owners_count":19833431,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["interview","interview-questions","javascript-questions"],"created_at":"2024-11-10T16:42:34.329Z","updated_at":"2025-02-25T09:26:30.178Z","avatar_url":"https://github.com/sunniejs.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"### JavaScript 题目 前端面试题目\r\n\r\n题目和答案通过网络整理，如有错误欢迎 pr 修正。\r\n\r\n题目可能不会按顺序添加，不要直接拉到最后哦，多看几遍吧，温故而知新。\r\n\r\n答案被折叠，点击即可查看答案。:heart:\r\n\r\n---\r\n\r\n#### js 七种数据类型？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n`Boolean`  \r\n`Null`  \r\n`Undefined`  \r\n`Number`  \r\n`String`  \r\n`Object`  \r\n`Symbol` (ECMAScript 6 新定义)  \r\n(ES6 之前)其中 5 种为基本类型:`string`,`number`,`boolean`,`null`,`undefined`  \r\nES6 出来的 `Symbol` 也是原始数据类型 ，表示独一无二的值  \r\n`Object` 为引用类型(范围挺大),也包括数组、函数\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### js 有哪几种方法定义函数？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n函数声明表达式\r\n\r\n```javascript\r\nvar func = function add(a, b) {\r\n    return a + b\r\n}\r\n```\r\n\r\nfunction 操作符\r\n\r\n```javascript\r\nvar func = function(a, b) {\r\n    return a + b\r\n}\r\n```\r\n\r\nFunction 构造函数\r\n\r\n```javascript\r\nvar func = new Function('a', 'b', 'return a + b')\r\n```\r\n\r\nES6:arrow function\r\n\r\n```javascript\r\nvar func = (a, b) =\u003e {\r\n    return a + b\r\n}\r\n```\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### `null` 和 `undefined` 的差异？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n相同点:\r\n\r\n在 `if` 判断语句中,值都默认为 `false`  \r\n大体上两者都是代表无,具体看差异\r\n\r\n差异:\r\n\r\n`null` 转为数字类型值为 0,而 `undefined` 转为数字类型为 `NaN`(Not a Number)  \r\n`undefined` 是代表调用一个值而该值却没有赋值,这时候默认则为 `undefined`  \r\n`null` 是一个很特殊的对象,最为常见的一个用法就是作为参数传入(说明该参数不是对象)  \r\n设置为 `null` 的变量或者对象会被内存收集器回收\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### 开发中用到了哪些 ES6 的新特性？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n1. `let` (声明变量) `const` (声明常量,常量不能修改的量)\r\n2. `class` (创建类)\r\n3. `import/export` (基于 ES6 的模块规范创建导入/导出模块(文件/组件))\r\n4. `new Set` (数组去重)\r\n5. `Symbol`(唯一的值) `var a = Symbol('sunnie')`\r\n6. `...ary` (展开运算符、剩余运算符)\r\n7. `${}` 模板字符串\r\n8. 解构赋值 `let {a} = obj; let [b] = ary`\r\n9. `for of` 循环\r\n10. `()=\u003e{}` 箭头函数\r\n11. 数组新增方法：`flat、find、findIndex`\r\n12. 对象新增方法： `Object.assign() Object.values() Object.keys() Object.create()`\r\n\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### `var` , `let` 和 `const` 的区别是什么？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n记住关键词：顶部变量属性、变量提升、暂时性死区、重复声明、初始值和作用域然后从这几个方向解释。\r\n\r\n| 声明方式 | 顶部变量属性 | 变量提升 | 暂时性死区 | 重复声明 | 初始值 | 作用域 |\r\n| -------- | ------------ | -------- | ---------- | -------- | ------ | ------ |\r\n| var      | 是           | 允许     | 不存在     | 允许     | 不需要 | 除块级 |\r\n| let      | 不是         | 不允许   | 存在       | 不允许   | 不需要 | 块级   |\r\n| const    | 不是         | 不允许   | 存在       | 不允许   | 需要   | 块级   |\r\n\r\n**顶部变量属性**： `var` 声明的变量会挂载在 window 上，而 `let` 和 `const` 声明的变量不会  \r\n**变量提升** ： `var` 变量可在声明之前使用，`let` 和 `const` 不可以  \r\n **暂时性死区**：`var`不存在暂时性死区，在代码块中，用 `let` 或 `const` 声明变量之前，使用会抛出异常 (暂时性死区)\r\n**重复声明** ： `var`允许重复声明，`let` 和 `const` 命令声明的变量不允许重复声明  \r\n **初始值**： `var`和 `let`可以没有初始值，由于 `const` 声明的是只读的常量，一旦声明，就必须立即初始化，声明之后值不能改变  \r\n **作用域**： `var` 没有块级作用域，`let` 和 `const`有块级作用域\r\n\r\n**拓展：修改 `const` 对象的某个属性会报错吗？**  \r\n因为对象是引用类型的，`const`仅保证指针不发生改变，修改对象的属性不会改变对象的指针，所以是被允许的。\r\n\r\n**拓展：输出什么？**\r\n\r\n```javascript\r\nconsole.log(a) // undefined\r\nvar a = 2\r\n\r\nconsole.log(b) //报错，Uncaught ReferenceError: b is not defined\r\nlet b = 1\r\n```\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### 几种 `for` 循环，以及区别？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n-   `forEach` `for`循环的简化,不能中断，没有 `break/continue` 方法，没有返回值。\r\n-   `map` 只能遍历数组，不能中断，返回值是修改后的数组。\r\n\r\n```javascript\r\nconst arr = [1, 2, 3, 4, 5]\r\nfor (let i = 0; i \u003c arr.length; i++) {}\r\n// ES5 forEach\r\narr.forEach(function(item) {})\r\n// ES5 every\r\narr.every(function(item) {\r\n    return true\r\n})\r\n// ES5 for in 循环的是 key\r\nconst object = { name: 'sunnie', age: 18 }\r\nfor (let key in object) {\r\n    console.log(key)\r\n}\r\n```\r\n\r\n```javascript\r\n// ES6 for of 循环的是 value\r\nfor (let item of object) {\r\n    console.log(key)\r\n}\r\n```\r\n\r\n**拓展：for...in 迭代和 for...of 有什么区别**\r\n\r\nfor...in 循环出的是 key，for...of 循环出的是 value\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### ES5,ES6 如何查找一个元素？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### 什么是类数组(伪数组)，如何转换成数组 ？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n`类数组(Array-Like Objects)` 是一个类似数组的对象，比如 `arguments` 对象，还有 `DOM API` 返回的 `NodeList` 对象都属于类数组对象。\r\n\r\n类数组对象有下面两个特性：\r\n\r\n-   具有：指向对象元素的数字索引下标和 `length` 属性\r\n-   不具有：比如 `push` 、`shift`、 `forEach` 以及 `indexOf` 等数组对象具有的方法\r\n\r\n**类数组对象转数组方法：**\r\n\r\n```javascript\r\nfunction fn() {\r\n    // ES5 方法1:\r\n    var arr = Array.prototype.slice.call(arguments)\r\n\r\n    // ES6 方法1:\r\n    let arr = Array.from(arguments)\r\n    // ES6 方法2:\r\n    let arr = [...arguments]\r\n\r\n    // 以上三种请任选一种执行测试，为方便写在一起了\r\n    arr.push(4) // arr -\u003e [1, 2, 3, 4]\r\n}\r\nfn(1, 2, 3)\r\n```\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### 箭头函数和普通函数的区别？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案:star:\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n-   箭头函数作为匿名函数，不能作为构造函数，不能使用 `new` 运算符\r\n-   箭头函数不绑定 `auguments`，用 `rest` 参数...解决\r\n-   箭头函数会捕获其上下文的 `this` 值，作为自己的 `this` 值\r\n-   箭头函数当方法使用的时候，没有定义 this 绑定\r\n-   使用`call()`和 `apply()`调用，传入参数时，参数一的改变对 `this` 没有影响\r\n-   箭头函数没有原型属性\r\n-   箭头函数不能当做 `Generator` 函数，不能使用 `yiel` 关键字。\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### JS 怎么实现一个类,怎么实例化这个类？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\nJavascript 传统方法是通过构造函数定义并生成新对象。\r\n\r\n```javascript\r\nfunction Parent(name) {\r\n    this.name = name\r\n}\r\nParent.prototype.eat = function() {\r\n    console.log('eat')\r\n}\r\nvar child = new Child('parent')\r\n```\r\n\r\nES6 引入了 `CLASS` 概念，`constructor`方法就是构造函数，定义 `类` 的方法时，前面不需要加 `function` 保留字，方法之前不需要逗号。\r\n\r\n```javascript\r\nclass Parent {\r\n    constructor(name) {\r\n        this.name = name\r\n    }\r\n    eat() {\r\n        console.log('eat')\r\n    }\r\n}\r\nlet child = new Child('parent')\r\n```\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### JS 怎么继承类？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n```javascript\r\n// ES5 call 继承\r\nfunction Parent() {\r\n    this.name = 'parent'\r\n}\r\nfunction Child() {\r\n    Parent.call(this)\r\n    this.type = 'child'\r\n}\r\n```\r\n\r\n缺点：只实现了部分继承 ，父类原型对象 `prototype` 上的方法无法继承。\r\n\r\n```javascript\r\n// ES5 借助原型链\r\nfunction Parent() {\r\n    this.name = 'parent'\r\n    this.play = [1, 2, 3]\r\n}\r\nfunction Child() {\r\n    Parent.call(this)\r\n}\r\nChild.prototype = new Parent()\r\n```\r\n\r\n通过上面的方法继承，尝试修改实例属性\r\n\r\n```javascript\r\nvar s1 = new Child()\r\nvar s2 = new Child()\r\ns1.play.push(4)\r\nconsole.log(s1.play, s2.play) // [1,2,3,4],[1,2,3,4]\r\n```\r\n\r\n缺点：实例化两个对象，修改其中一个对象的继承属性，另外也会改变。因为两个实例的原型对象一样。\r\n\r\n```javascript\r\n// ES5 借助Call和原型链\r\nfunction Parent() {\r\n    this.name = 'parent'\r\n    this.play = [1, 2, 3]\r\n}\r\nfunction Child() {\r\n    Parent.call(this)\r\n    this.type = 'child'\r\n}\r\nChild.prototype = new Parent()\r\n```\r\n\r\n缺点：多执行了一次构造函数会 `Child3.prototype = new Parent()`\r\n\r\n```javascript\r\nfunction Parent() {\r\n    this.name = 'parent'\r\n    this.play = [1, 2, 3]\r\n}\r\nfunction Child() {\r\n    Parent.call(this)\r\n    this.type = 'child'\r\n}\r\nChild.prototype = Parent.prototype\r\n```\r\n\r\n缺点：多执行了一次构造函数会 `Child3.prototype = new Parent()`\r\n\r\n```javascript\r\n// 只实现了部分继承 ，prototype上的没有被继承\r\nfunction Animal(type) {\r\n    this.type = type\r\n}\r\nfunction Dog() {\r\n    Animal.call(this)\r\n}\r\n```\r\n\r\n```javascript\r\n// ES6 实现继承\r\nclass Animal {\r\n    construtor(type) {\r\n        this.type = type\r\n    }\r\n    eat() {\r\n        console.log('eat')\r\n    }\r\n}\r\nclass Dog extends Animal {\r\n    construtor(type) {\r\n        supper(type)\r\n    }\r\n}\r\n```\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### ES6 `Set()` `Map()` 添加值得方法？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n添加值方法： `Set` 使用`add`添加，`Map` 使用`set`添加\r\n\r\n```javascript\r\n// Set\r\nlet mySet = new Set()\r\nmySet.add(1)\r\n// Map\r\nconst myMap = new Map()\r\nconst o = { p: 'hello' }\r\nmyMap.set(o, 'world')\r\n```\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### es6 class static 解释？如何继承 static？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n类相当于实例的原型，所有在类中定义的方法，都会被实例继承。如果在一个方法前，加上`static`关键字，就表示该方法不会被实例继承，而是直接通过类来调用，这就称为“静态方法”。\r\n\r\n-   静态方法调用直接在类上进行，而在类的实例上不可被调用。\r\n-   父类的静态方法，可以被子类继承。\r\n\r\n```javascript\r\nclass Foo {\r\n    static classMethod() {\r\n        return 'hello'\r\n    }\r\n}\r\n// 静态方法调用直接在类上进行，而在类的实例上不可被调用。\r\nFoo.classMethod() // 'hello'\r\nvar foo = new Foo()\r\nfoo.classMethod() // TypeError: foo.classMethod is not a function\r\n\r\n// 父类的静态方法，可以被子类继承。\r\nclass Bar extends Foo {}\r\nBar.classMethod() // 'hello'\r\n```\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### 什么闭包,闭包有什么用？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案:star:\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### JS 如何获取函数所有参数？\r\n\r\n知识点：`rest参数` `类数组`\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n```javascript\r\n// ES5\r\nfunction sum() {\r\n    console.log(arguments)\r\n}\r\n// ES6\r\nfunction sum(...rest) {\r\n    // rest 是数组\r\n    console.log(rest)\r\n}\r\nsum(1, 2, 3)\r\n```\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### 用箭头函数实现一个数组排序？\r\n\r\n知识点：`sort` `箭头函数`\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n```javascript\r\nconst arr = [10, 5, 40, 25, 1000, 1]\r\n\r\narr.sort((a, b) =\u003e {\r\n    return a - b\r\n})\r\nconsole.log(arr) // [1, 5, 10, 25, 40, 1000]\r\n```\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### 如何用箭头函数时间一个数组排序？\r\n\r\n知识点：`Object`\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### 深拷贝和浅拷贝的区别，以及实现？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案:star:\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n`浅拷贝`只复制指向某个对象的指针，而不复制对象本身，新旧对象还是共享同一块内存。  \r\n`深拷贝`会另外创造一个一模一样的对象，新对象跟原对象不共享内存，修改新对象不会改到原对象。\r\n\r\n**如何实现浅拷贝:**\r\n\r\n```javascript\r\nfunction clone(target) {\r\n    let cloneTarget = {}\r\n    for (const key in target) {\r\n        cloneTarget[key] = target[key]\r\n    }\r\n    return cloneTarget\r\n}\r\n```\r\n\r\n**如何实现深拷贝:**\r\n\r\n如果你的对象**没有**复杂类型的数据如 `Dates`, `functions`, `undefined`, `Infinity`, `RegExps`, `Maps`, `Sets`, `Blobs`等 简单的实现方法：\r\n\r\n```javascript\r\nJSON.parse(JSON.stringify())\r\n```\r\n\r\n基础款：\r\n\r\n```javascript\r\nfunction clone(target) {\r\n    if (typeof target === 'object') {\r\n        let cloneTarget = {}\r\n        for (const key in target) {\r\n            cloneTarget[key] = clone(target[key])\r\n        }\r\n        return cloneTarget\r\n    } else {\r\n        return target\r\n    }\r\n}\r\n```\r\n\r\n拷贝的时候不能只考虑数组，还有其他类型，以及考虑性能，这里直接来看大神如何一步一步实现：  \r\n[如何写出一个惊艳面试官的深拷贝?](https://juejin.im/post/5d6aa4f96fb9a06b112ad5b1)\r\n\r\n**ES6 `Object.assign()` 是深拷贝还是浅拷贝？**\r\n\r\n`Object.assign`方法实行的是浅拷贝，不是深拷贝。  \r\n也就是说，如果源对象某个属性的值是对象，那么目标对象拷贝得到的是这个对象的引用。  \r\n注意:object 只有一层的时候，是深拷贝\r\n\r\n```javascript\r\nlet obj = {\r\n    username: 'sunnie',\r\n}\r\nlet obj2 = Object.assign({}, obj)\r\nobj2.username = 'change' // `深拷贝`修改新对象不会改到原对象\r\nconsole.log(obj) // {username: \"sunnie\"}\r\n```\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### this？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### `call`、`apply`、`bind`的区别,以及实现？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案:star:\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n`apply` 、`call`、`bind` 都是可以改变 `this` 的指向的，但是这三个函数稍有不同。\r\n\r\n**先说 apply 和 call 的区别**\r\n\r\n`call()`方法接受的是参数列表，而`apply()`方法接受的是一个参数数组。\r\n\r\n```javascript\r\nvar person = {\r\n    value: 1,\r\n}\r\nfunction say(name, age) {\r\n    console.log(name)\r\n    console.log(age)\r\n    console.log(this)\r\n}\r\n// call 用法\r\nsay.call(person, 'sunnie', 18)\r\n// apply 用法\r\nsay.apply(person, ['sunnie', 18])\r\n// kevin\r\n// 18\r\n// {value: 1}\r\n```\r\n\r\n看完之后还是很疑惑为什么会有这个玩意??\r\n\r\n说改变`this`的指向太抽象。我们这样理解：有一个对象 `person` ,懒得给它新定义 `say` 方法，  \r\n就通过 `call` 或 `apply`,用 `say.call(person)` 给 `person` 添加一个 `say` 方法，并执行它。  \r\n这个时候`this` 从原来的 `window` 改成了 `person` 。\r\n\r\n**call 实现**\r\n\r\n思路：1.将函数设为对象的属性 2.执行该函数 3.删除该函数\r\n\r\n```javascript\r\n// 第一版\r\nFunction.prototype.call2 = function(context) {\r\n    // 首先要获取调用 call 的函数，用this可以获取\r\n    context.fn = this\r\n    context.fn()\r\n    delete context.fn\r\n}\r\n```\r\n\r\n**apply 实现**\r\n\r\n`apply` 与 `call` 类似，直接去看大神怎么一步一步实现\r\n\r\n\u003ca href=\"https://juejin.im/post/5907eb99570c3500582ca23c\" target=\"_blank\"\u003eJavaScript 深入之 call 和 apply 的模拟实现\u003c/a\u003e\r\n\r\n**bind 与 apply 、call 的区别**\r\n\r\n`bind` 返回值为一个修改完 `this` 指向的函数，需要主动调用\r\n\r\n```javascript\r\n// 第一版\r\nFunction.prototype.bind2 = function(context) {\r\n    var self = this\r\n    return function() {\r\n        self.apply(context)\r\n    }\r\n}\r\n```\r\n\r\n这里直接来看大神如何一步一步实现：  \r\n\u003ca href=\"https://juejin.im/post/59093b1fa0bb9f006517b906\" target=\"_blank\"\u003eJavaScript 深入之 call 和 apply 的模拟实现\u003c/a\u003e\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### 如何实现防抖、节流？应用场景？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n \r\n**`函数防抖`(debounce):防抖就是将一段时间内连续的多次触发转化为一次触发。**\r\n\r\n比如：我点击一个按钮，`delay`设置 3s ,我手速超快，从来不让点击间隔时间大于 3s 函数就不执行，一旦大于了 3s 就执行了\r\n\r\n```javascript\r\nfunction debounce(func, delay) {\r\n    let timeout\r\n    return function() {\r\n        clearTimeout(timeout) // 如果持续触发，那么就清除定时器，定时器的回调就不会执行。\r\n        timeout = setTimeout(() =\u003e {\r\n            func.apply(this, arguments)\r\n        }, delay)\r\n    }\r\n}\r\n```\r\n\r\n**`函数节流`(throttle):节流顾名思义则是将减少一段时间内触发的频率。**\r\n\r\n比如：我点击一个按钮，`threshhold`设置 3s, 当我点第一次点击执行函数，接下来的 3s 内点都少次都没用，直到距离第一次 3s 执行第二次\r\n\r\n```javascript\r\nfunction throttle(fn, threshhold = 3000) {\r\n    let last\r\n    let timer\r\n    return function() {\r\n        const now = +new Date()\r\n        if (last \u0026\u0026 now \u003c last + threshhold) {\r\n            clearTimeout(timer)\r\n            timer = setTimeout(() =\u003e {\r\n                last = now\r\n                fn.apply(this, arguments)\r\n            }, threshhold)\r\n        } else {\r\n            last = now\r\n            fn.apply(this, arguments)\r\n        }\r\n    }\r\n}\r\n```\r\n\r\n**应用场景**\r\nmouse move 时减少计算次数：`debounce`  \r\ninput 中输入文字自动发送 ajax 请求进行自动补全： `debounce`  \r\najax 请求合并，不希望短时间内大量的请求被重复发送：`debounce`  \r\nresize window 重新计算样式或布局：`debounce` 或 `throttle`  \r\nscroll 时触发操作，如随动效果：throttle  \r\n对用户输入的验证，不想停止输入再进行验证，而是每 n 秒进行验证：`throttle`\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### ES6 Async/Await 与 Promise 区别？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### `script` 引入标签 `defer` 和 `async` 区别和相同点？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n![](https://imgs.solui.cn/questions/defer.png)\r\n\r\n通过图片观察  \r\n相同：\r\n\r\n-   加 `defer` 和 `async`后，`script`读取和 `html`解析同时进行，不会阻塞 `html` 解析。  \r\n    不同：\r\n-   `defer`会在 `html`解析完之后执行 ， `async` 则是异步加载完 `script` 后立即执行 。\r\n-   图中未表现出 `defer` 是按照加载顺序执行脚本的。 `async` 则是一个乱序执行，反正对它来说脚本的加载和执行是紧紧挨着的，所以不管你声明的顺序如何，只要它加载完了就会立刻执行。\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n\r\n#### 如何找到失散已久的组织？\r\n\r\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003e答案\u003c/b\u003e\u003c/summary\u003e\r\n\u003cp\u003e\r\n \r\n \u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;扫描下方二维码:point_down::point_down:关注“前端女塾”\r\n\r\n![logo](https://imgs.solui.cn/wx/640.gif ':size=262x224')  \r\n关注公众号：回复“加群”即可加 前端仙女群\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n---\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsunniejs%2Fjavascript-question","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsunniejs%2Fjavascript-question","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsunniejs%2Fjavascript-question/lists"}