当前位置: 首页 > news >正文

0716网站建设兰州网站怎么建设

0716网站建设,兰州网站怎么建设,上海网站建设褐公洲司,苏州找工作网站有哪些近期整理了一下高频的前端面试题#xff0c;分享给大家一起来学习。如有问题#xff0c;欢迎指正#xff01; 1. JavaScript有哪些数据类型 总共有8种数据类型#xff0c;分别是Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt Null 代表的含义是空对象… 近期整理了一下高频的前端面试题分享给大家一起来学习。如有问题欢迎指正 1. JavaScript有哪些数据类型 总共有8种数据类型分别是Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt Null 代表的含义是空对象主要用于赋值给一些可能会返回对象的变量作为初始化 Undefined 代表的含义是未定义一般变量声明了但还没有定义值的时候就会返回undefined Symbol 代表创建后独一无二且不可变的数据类型它主要是为了解决可能出现的全局变量冲突问题 BigInt 是一种数字类型的数据它可以表示任意精度格式的整数使用BigInt可以安全的存储和操作大整数即使这个数已经超出了Number能够表示的安全整数范围 原始数据类型Undefined、Null、Boolean、Number、String、Symbol、BigInt引用数据类型Object、Array、Function、RegExp、Date、Global、Math等 原始数据类型与引用数据类型的区别 原始数据类型直接存储在栈stack中的简单数据段占据空间小、大小固定数据被频繁使用的数据可以放入栈中存储 引用数据类型存储在堆heap中的对象占据空间大、大小不固定。在栈中存储指针该指针指向堆中该实体的起始地址。当解释器寻找引用值时会首先检索其在栈中的地址取得地址后从堆中获得实体。 2. 数据类型检测方式有哪些 1. typeof typeof可以区分除了Null类型以外的其他基本数据类型以及从对象类型中识别出函数function。 其返回值有number、string、boolean、undefined、symbol、bigint、function、object。 其中, typeof null返回 object 如果要识别null可直接使用全等运算符来判断 console.log(typeof 2); // number console.log(typeof str); // string console.log(typeof true); // boolean console.log(typeof undefined); // undefined console.log(typeof Symbol()); // symbol console.log(typeof BigInt(2782371)); // bigint console.log(typeof []); // object console.log(typeof function(){}); // function console.log(typeof {}); // object console.log(typeof null); // object2. instanceof instanceof一般用来判断引用数据类型但不能正确判断基本数据类型根据在原型链中查找判断当前数据的原型对象是否存在返回布尔类型值 console.log(2 instanceof Number); // false console.log(true instanceof Boolean); // false console.log(str instanceof String); // false console.log([] instanceof Array); // true console.log(function(){} instanceof Function); // true console.log({} instanceof Object); // true let date new Date(); console.log(date instanceof Date); // trueinstanceof实现方式 function myInstanceof(left, right) {// 获取对象的原型let proto Object.getPrototypeOf(left)// 获取构造函数的 prototype 对象let prototype right.prototype; // 判断构造函数的 prototype 对象是否在对象的原型链上while (true) {if (!proto) return false;if (proto prototype) return true;// 如果没有找到就继续从其原型上找Object.getPrototypeOf方法用来获取指定对象的原型proto Object.getPrototypeOf(proto);} }3. constructor console.log((2).constructor Number); // true console.log((true).constructor Boolean); // true console.log((str).constructor String); // true console.log(([]).constructor Array); // true console.log((function() {}).constructor Function); // true console.log(({}).constructor Object); // trueconstructor有两个作用一是判断数据的类型二是对象实例通过constructor对象访问它的构造函数。 需要注意如果创建一个对象来改变它的原型constructor就不能用来判断数据类型 function Fn(){}; Fn.prototype new Array(); const f new Fn(); console.log(f.constructorFn); // false console.log(f.constructorArray); // true4. Object.prototype.toString.call() Object.prototype.toString.call()使用Object对象的原型方法toString来判断数据类型 const objectJudgment value Object.prototype.toString.call(value).slice(8, -1); console.log(Object.prototype.toString.call(1)) // [object Number] console.log(objectJudgment(2)); // Number console.log(objectJudgment(true)); // Boolean console.log(objectJudgment(str)); // String console.log(objectJudgment([])); // Array console.log(objectJudgment(function(){})); // Function console.log(objectJudgment({})); // Object console.log(objectJudgment(undefined)); // Undefined console.log(objectJudgment(null)); // Null console.log(objectJudgment(/123/g)); // RegExp console.log(objectJudgment(new Date())); // Date console.log(objectJudgment(document)); // HTMLDocument console.log(objectJudgment(window)); // Window3. 判断数组的方式 通过Object.prototype.toString.call()做判断 Object.prototype.toString.call(obj).slice(8,-1) Array;通过原型链做判断 obj.__proto__ Array.prototype;通过ES6的Array.isArray()做判断 Array.isArrray(obj);通过instanceof做判断 obj instanceof Array通过Array.prototype.isPrototypeOf Array.prototype.isPrototypeOf(obj)4. isNaN 和 Number.isNaN 函数的区别 isNaN函数会首先尝试将这个参数转换为数值然后才会对转换后的结果是否是NaN进行判断任何不能被转换为数值的的值都会返回 true因此非数字值传入也会返回 true 会影响 NaN 的判断。 函数 Number.isNaN 会首先判断传入参数是否为数字如果是数字再继续判断是否为 NaN 不会进行数据类型的转换这种方法对于 NaN 的判断更为准确。 5. ||和操作符的返回值 ||和首先会对第一个操作数执行条件判断如果其不是布尔值就先强制转换为布尔值然后再执行条件判断 ||如果条件判断结果为true就返回第一个操作数的值如果为false就返回第二个操作数的值 如果条件判断结果为true就返回第二个操作数的值如果为false就返回第一个操作数的值 6. Object.is()与比较操作符、的区别 使用双等号进行相等判断时如果两边的类型不一致则会进行强制类型转化后再进行比较。 使用三等号进行相等判断时如果两边的类型不一致时不会做强制类型准换直接返回 false。 使用 Object.is 来进行相等判断时一般情况下和三等号的判断相同它处理了一些特殊的情况比如 -0 和 0 不再相等两个 NaN 是相等的。 7. 如何 遍历对象的属性 遍历自身可枚举的属性可枚举、非继承属性Object.keys该方法会返回一个由给定对象的自身可枚举属性组成的数组 遍历自身的所有属性可枚举、不可枚举、非继承属性Object.getOwnPropertyNames()该方法会返回一个由指定对象的所有自身属性组成的数组 遍历 可枚举的自身属性和继承属性for...in... 8. for...in和for...of的区别 for...in获取的是对象的键名for...of获取的是对象的键值for...in会遍历对象的整个原型链性能非常差不推荐使用for...of只会遍历当前对象不会遍历原型链对于数组的遍历for...in会返回数组中所有可枚举的属性包括原型链上可枚举的属性for...of只会返回数组的下标对应的属性值 总结 for...in循环主要是为了遍历对象不适用于遍历数组for...of循环可以用来遍历数组、类数组对象、字符串、Set、Map、Generator对象 9. JavaScript中的遍历方法 方法特点forfor循环有三个表达式组成分别是声明循环变量、判断循环条件、更新循环变量。这三个表达式用分号分隔都可以省略但中间的分号不能省略。在执行时候会先判断执行条件再执行。可以用来 遍历数组、字符串、类数组、DOM节点等whilewhile循环中的结束条件可以是各种类型但是始终都会转为增加值转换规则Boolean–true为真false为假String–空字符串为假其余为真Number–0为假其余为真Null、Undefined、NaN全为假Object全为真。在执行的时候会先判断再执行。do/while先执行再判断即使初始条件不成立do/while循环至少执行一次。for await…offor await...of方法被称为异步迭代器该方法是主要用来遍历异步对象。for await...of 语句会在异步或者同步可迭代对象上创建一个迭代循环包括 StringArray类数组Map Set和自定义的异步或者同步可迭代对象。这个语句只能在 async function内使用。map()map() 方法会返回一个新数组数组中的元素为原始数组元素调用函数处理后的值。该方法按照原始数组元素顺序依次处理元素。注意 map() 不会对空数组进行检测它会返回一个新数组不会改变原始数组。该方法的第一个参数为回调函数他有三个参数currentValue 必须。当前元素的值、index 可选。当前元素的索引值、arr 可选。当前元素属于的数组对象。第二个参数用来绑定参数函数内部的this变量可选。forEach()forEach 方法用于调用数组的每个元素并将元素传递给回调函数。数组中的每个值都会调用回调函数回调函数有三个参数currentValue必需。当前元素、index可选。当前元素的索引值、arr 可选。当前元素所属的数组对象。该方法还可以有第二个参数用来绑定回调函数内部this变量前提是回调函数不能是箭头函数因为箭头函数没有this。需要注意的是forEach方法不会改变原数组也没有返回值。filter()filter()方法用于过滤数组满足条件的元素会被返回。它的参数是一个回调函数所有数组元素依次执行该函数返回结果为true的元素会被返回。该方法会返回一个新的数组不会改变原数组。该方法的第一个参数是回调函数它有三个参数currentValue必须。当前元素的值、index可选。当前元素的索引值、arr可选。当前元素属于的数组对象。该方法有第二个参数用来绑定参数函数内部的this变量。every()和some()数组方法some()只要有一个是true即返回true而every()只要有一个是false即返回falsefind()和findIndex()数组方法find()返回的是第一个符合条件的值findIndex()返回的是第一个返回条件的值的索引值reduce()和reduceRight()数组方法reduce()对数组正序操作reduceRight()对数组逆序操作Object.keys()和Object.getOwnPropertyNames()Object.keys() 获取对象可枚举的属性Object.getOwnPropertyNames() 返回所有属性两者都返回一个包含属性名的数组 10. 强制类型转换和隐式类型转换 强制 转换成字符串1.toString()、String(1) 转换成数字Number(2)、parseInt()、parseFloat() 转换成布尔Boolean() 隐式 1 23 // 123 1 false // 1 1 Symbol() // Uncaught TypeError: Cannot convert a Symbol value to a number 1 false // 1false false true // 1-、*、/ 1 * 23 // 23 1 * false // 0 1 / aa // NaN3 true // false, 3 转为number为3true转为number为1 0 false //true, 0转为number为0false转为number为0 0 0 // 0转为number为011. JavaScript的作用域和作用域链 作用域即变量和函数生效的区域或集合。作用域决定了代码块中变量和其他资源的可见性。一般分为全局作用域、局部作用域 作用域链当在 JS 中使用一个变量时JS 引擎会尝试在当前作用域下寻找该变量如果没找到再到它的上层作用域寻找以此类推直至找到该变量或是查找至全局作用域如果在全局作用域里仍然找不到该变量它就会在全局范围内隐式声明该变量(非严格模式下)或是直接报错。 全局作用域定义的变量可以被任何地方访问。 最外层定义的函数和最外层函数之外定义的变量拥有全局作用域 window上的属性都具有全局作用域在JavaScript中window lobal 局部作用域与全局作用域相反局部作用域内的变量只能被定义它的局部作用域访问 函数作用域内的变量和函数只能由函数内部访问。作用域是分层的内部函数可以访问外部函数作用域里的变量反之不可以 块级作用域凡是代码块就可以划分变量的作用域这种作用域的规则就叫做块级作用域。 12. let、const、var的区别 1. 块级作用域 块作用域由 { }包括let和const具有块级作用域var不存在块级作用域。块级作用域解决了ES5中的两个问题 内层变量可能覆盖外层变量用来计数的循环变量泄露为全局变量 2. 变量提升 var存在变量提升let和const不存在变量提升即在变量只能在声明之后使用否则会报错。 3. 给全局添加属性 浏览器的全局对象是windowNode的全局对象是global。var声明的变量为全局变量并且会将该变量添加为全局对象的属性但是let和const不会。 4. 重复声明 var声明变量时可以重复声明变量后声明的同名变量会覆盖之前声明的遍历。const和let不允许重复声明变量。 5. 暂时性死区 在使用let、const命令声明变量之前该变量都是不可用的。这在语法上称为暂时性死区。使用var声明的变量不存在暂时性死区。 6. 初始值设置 在变量声明时var 和 let 可以不用设置初始值。而const声明变量必须设置初始值。 7. 指针指向 let和const都是ES6新增的用于创建变量的语法。 let创建的变量是可以更改指针指向可以重新赋值。但const声明的变量是不允许改变指针的指向。 13. new操作符具体做了什么如何实现 首先创建一个新的空对象设置原型让对象的原型设置为函数的prototype对象让函数的this指向这个对象执行构造函数的代码判断函数的返回值类型如果是值类型返回创建的对象如果是引用类型就返回这个引用类型的对象 实现代码 function objectFactory() {let newObject null;let constructor Array.prototype.shift.call(arguments);let result null;// 参数判断if (typeof constructor ! function) {console.error(type error);return;}// 新建一个空对象对象的原型为构造函数的 prototype 对象newObject Object.create(constructor.prototype);// 将 this 指向新建对象并执行函数result constructor.apply(newObject, arguments);// 判断返回对象let flag result (typeof result object || typeof result function);// 判断返回结果return flag ? result : newObject; }12. Map与Object的区别 MapObject意外的键Map默认情况不包含任何键只包含显示插入的键Object有一个原型原型链上的键名有可能和自己在对象上设置的键名产生冲突键的类型Map的键可以是任意值包括函数、对象或任意基本类型Object的键必须是String或者Symbol键的顺序Map中的key是有序的。因此当迭代的时候Map对象以插入的顺序返回键值Object的键是无序的SizeMap的键值对个数可以轻易的通过size属性获取Object的键值对个数只能手动计算迭代Map是iterable的所以可以直接被迭代迭代Object需要以某种方式获取它的键然后迭代性能在频繁增删键值对的场景下表现更好在频繁增删键值对的场景下未作出优化 15. JavaScript的内置对象 1值属性这些全局属性返回一个简单值这些值没有自己的属性和方法。例如 Infinity、NaN、undefined、globalThis 2函数属性全局函数可以直接调用不需要在调用时指定所属对象执行结束后会将结果直接返回给调用者。例如 eval()、uneval()、isFinite()、isNaN()、parseFloat()、parseInt()、decodeURI()、decodeURIComponent()、encodeURI()encodeURIComponent() 3基本对象基本对象是定义或使用其他对象的基础。基本对象包括一般对象、函数对象和错误对象。例如 Object、Function、Boolean、Symbol 4错误对象错误对象是一种特殊的基本对象。它们拥有基本的 Error 类型同时也有多种具体的错误类型。例如 Error、AggregateError、EvalError、InternalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError 5数字和日期对象用来表示数字、日期和执行数学计算的对象。例如 Number、BigInt、Math、Date 6字符串用来表示和操作字符串的对象。例如 String、RegExp 7可索引的集合对象这些对象表示按照索引值来排序的数据集合包括数组和类型数组以及类数组结构的对象。例如 Array 8使用键的集合对象这些集合对象在存储数据时会使用到键支持按照插入顺序来迭代元素。 例如 Map、Set、WeakMap、WeakSet 9结构化数据这些对象用来表示和操作结构化的缓冲区数据或使用 JSON 编码的数据。例如 JSON、ArrayBuffer、DateView、Atomics 10控制抽象对象控件抽象可以帮助构造代码尤其是异步代码。例如 Promise、Generator、GeneratorFunction、AsyncFunction 11反射 例如 Reflect、Proxy 12国际化ECMAScript 核心的附加功能用于支持多语言处理。例如 Intl、Intl.Collator、Intl.DateTimeFormat、Intl.ListFormat、Intl.NumberFormat、Intl.PluralRules、Intl.RelativeTimeFormat、Intl.Locale 13WebAssembly 例如 - WebAssembly、WebAssembly.Module、WebAssembly.Instance、WebAssembly.Memory、WebAssembly.Table、WebAssembly.CompileError、WebAssembly.RuntimeError 14其他 例如 arguments 16. 对JSON的理解 JSON 对象包含两个方法用于解析 JSON 的 parse() 方法以及将对象/值转换为 JSON 字符串的 stringify() 方法。除了这两个方法JSON 这个对象本身并没有其他作用也不能被调用或者作为构造函数调用。JSON 是一种语法用来序列化对象、数组、数值、字符串、布尔值和 null 。 JSON.stringify() 方法将一个 JavaScript 对象或值转换为 JSON 字符串如果指定了一个 replacer 函数则可以选择性地替换值或者指定的 replacer 是数组则可选择性地仅包含数组指定的属性。当在循环引用时会抛出异常TypeError当尝试去转换 BigInt 类型的值会抛出TypeError。 转换值如果有 toJSON() 方法该方法定义什么值将被序列化。非数组对象的属性不能保证以特定的顺序出现在序列化后的字符串中。布尔值、数字、字符串的包装对象在序列化过程中会自动转换成对应的原始值。undefined、任意的函数以及 symbol 值在序列化过程中会被忽略出现在非数组对象的属性值中时或者被转换成 null出现在数组中时。函数、undefined 被单独转换时会返回 undefined如JSON.stringify(function(){}) or JSON.stringify(undefined).对包含循环引用的对象对象之间相互引用形成无限循环执行此方法会抛出错误。所有 以 symbol 为属性键的属性都会被完全忽略掉即便 replacer 参数中强制指定包含了它们。Date 日期调用了 toJSON() 将其转换为了 string 字符串同 Date.toISOString()因此会被当做字符串处理。NaN 和 Infinity 格式的数值及 null 都会被当做 null。其他类型的对象包括 Map/Set/WeakMap/WeakSet仅会序列化可枚举的属性。 JSON.parse() 方法用来解析 JSON 字符串构造由字符串描述的 JavaScript 值或对象。提供可选的 reviver 函数用以在返回之前对所得到的对象执行变换 (操作)。若传入的字符串不符合 JSON 规范则会抛出 SyntaxError 异常。当从后端接收到 JSON 格式的字符串时可以通过这个方法来将其解析为一个 js 数据结构以此来进行数据的访问。 17. 数组的原生方法 数组和字符串的转换方法toString()、toLocalString()、join() 其中 join() 方法可以指定转换为字符串时的分隔符。 数组尾部操作的方法 pop() 和 push()push 方法可以传入多个参数。 数组首部操作的方法 shift() 和 unshift() 重排序的方法 reverse() 和 sort()sort 方法可以传入一个函数来进行比较传入前后两个值如果返回值为正数则交换两个参数的位置。 数组连接的方法 concat() 返回的是拼接好的数组不影响原数组。 数组截取办法 slice()用于截取数组中的一部分返回不影响原数组。 数组插入方法 splice()影响原数组查找特定项的索引的方法indexOf() 和 lastIndexOf() 迭代方法 every()、some()、filter()、map() 和 forEach() 方法 数组归并方法 reduce() 和 reduceRight() 方法 数组取值的方法 at()接收一个整数值并返回该索引对应的元素允许正数和负数。负整数从数组中的最后一个元素开始倒数 18. this 的理解 this是 JS 的一个关键字它是函数运行时自动生成的一个内部对象只能在函数内部使用随着函数使用场合的不同this的值会发生变化但有一个总的原则this指的是调用函数的那个对象。 this的绑定规则 默认绑定、隐式绑定、显示绑定、new绑定、ES6新增箭头函数绑定 默认绑定通常是指函数独立调用不涉及其他绑定规则非严格模式下this指向window严格模式下this指向undefined 非严格模式print()为默认绑定this指向window所以打印window和234 var foo 123; function print(){this.foo 234;console.log(this); // windowconsole.log(foo); // 234 } print();严格模式函数内部this指向undefined但全局对象window不会受影响 use strict; var foo 123; function print(){console.log(print this is , this); // print this is undefinedconsole.log(window.foo); // 123console.log(this.foo); // Uncaught TypeError: Cannot read property foo of undefined } console.log(global this is , this); // global this is Window{...} print();let/constlet/const定义的变量存在暂时性死区而且不会挂载到window对象上因此print中是无法获取到a和b的 let a 1; const b 2; var c 3; function print() {console.log(this.a); // undefinedconsole.log(this.b); // undefinedconsole.log(this.c); // 3 } print(); console.log(this.a); // undefined对象内执行foo虽然在obj的bar函数中但foo函数仍然是独立运行的foo中的this依旧指向window对象 a 1; function foo() {console.log(this.a); } const obj {a: 10,bar() {foo(); // 1} } obj.bar(); 自执行函数this指向window 自执行函数只要执行到就会运行并且只会运行一次this指向window a 1; (function(){console.log(this); // Window{...}console.log(this.a); // 1 }()) function bar() {b 2;(function(){console.log(this); // Window{...}console.log(this.b); // 2}()) } bar();隐式绑定函数的调用是在某个对象上触发的即调用位置存在上下文对象通俗点说就是XXX.func()这种调用模式。此时func的this指向XXX但如果存在链式调用例如XXX.YYY.ZZZ.func记住一个原则this永远指向最后调用它的那个对象 隐式绑定obj是通过var定义的obj会挂载到window之上的obj.foo()就相当于window.obj.foo()这也印证了this永远指向最后调用它的那个对象规则 var a 1; function foo() {console.log(this.a); } // 对象简写等同于 {a:2, foo: foo} var obj {a: 2, foo} foo(); // 1 obj.foo(); // 2对象链式调用 var obj1 {a: 1,obj2: {a: 2,foo(){console.log(this.a)}} } obj1.obj2.foo() // 2显示绑定比较好理解就是通过call()、apply()、bind()等方法强行改变this指向 上面的方法虽然都可以改变this指向但使用起来略有差别 call()和apply()函数会立即执行bind()函数会返回新函数不会立即执行函数call()和apply()的区别在于call接受若干个参数apply接受数组。 function foo () {console.log(this.a); }; var obj { a: 1 }; var a 2;foo(); // 2 foo.call(obj); // 1 foo.apply(obj); // 1 foo.bind(obj);function foo() {console.log(this.a); }; function doFoo(fn) {console.log(this); // { a: 1, foo:f}fn.call(this); // 1 } var obj { a: 1, foo }; var a 2; doFoo.call(obj, obj.foo);new绑定通过new来调用构造函数会生成一个新对象并且把这个新对象绑定为调用函数的this function Foo(){getName function(){ console.log(1); };return this; } Foo.getName function(){ console.log(2); }; Foo.prototype.getName function(){ console.log(3); }; var getName function(){ console.log(4); }; function getName(){ console.log(5) };Foo.getName(); // 2 getName(); // 4 Foo().getName(); // 1 getName(); // 1 new Foo.getName(); // 2 new Foo().getName(); // 3 new new Foo().getName(); // 3箭头函数没有自己的this它的this指向外层作用域的this且指向函数定义时的this而非执行时 name tom const obj {name: zc,intro: () {console.log(My name is this.name)} } obj.intro(); // My name is tom19. 实现call、apply、bind函数 call 函数的实现步骤 判断调用对象是否为函数即使是定义在函数的原型上的但是可能出现使用 call 等方式调用的情况。判断传入上下文对象是否存在如果不存在则设置为 window 。处理传入的参数截取第一个参数后的所有参数。将函数作为上下文对象的一个属性。使用上下文对象来调用这个方法并保存返回结果。删除刚才新增的属性。返回结果。 Function.prototype.myCall function(context) {// 判断调用对象if (typeof this ! function) {console.error(type error);}// 获取参数let args [...arguments].slice(1),result null;// 判断 context 是否传入如果未传入则设置为 windowcontext context || window;// 将调用函数设为对象的方法context.fn this;// 调用函数result context.fn(...args);// 将属性删除delete context.fn;return result; };apply 函数的实现步骤 判断调用对象是否为函数即使是定义在函数的原型上的但是可能出现使用 call 等方式调用的情况。判断传入上下文对象是否存在如果不存在则设置为 window 。将函数作为上下文对象的一个属性。判断参数值是否传入使用上下文对象来调用这个方法并保存返回结果。删除刚才新增的属性返回结果 Function.prototype.myApply function(context) {// 判断调用对象是否为函数if (typeof this ! function) {throw new TypeError(Error);}let result null;// 判断 context 是否存在如果未传入则为 windowcontext context || window;// 将函数设为对象的方法context.fn this;// 调用方法if (arguments[1]) {result context.fn(...arguments[1]);} else {result context.fn();}// 将属性删除delete context.fn;return result; };bind 函数的实现步骤 判断调用对象是否为函数即使是定义在函数的原型上的但是可能出现使用 call 等方式调用的情况。保存当前函数的引用获取其余传入参数值。创建一个函数返回函数内部使用 apply 来绑定函数调用需要判断函数作为构造函数的情况这个时候需要传入当前函数的 this 给 apply 调用其余情况都传入指定的上下文对象 Function.prototype.myBind function(context) {// 判断调用对象是否为函数if (typeof this ! function) {throw new TypeError(Error);}// 获取参数var args [...arguments].slice(1),fn this;return function Fn() {// 根据调用方式传入不同绑定值return fn.apply(this instanceof Fn ? this : context,args.concat(...arguments));}; };20. 箭头函数与普通函数的区别 箭头函数比普通函数更加简洁箭头函数没有自己的this箭头函数继承来的this指向永远不会改变call()、apply()、bind()等方法不能改变箭头函数中this的指向箭头函数不能作为构造函数使用箭头函数没有自己的arguments箭头函数没有prototype箭头函数不能用作Generator函数不能使用yelid关键字 21. 浅拷贝和深拷贝的实现 浅拷贝如果属性是基本类型拷贝的就是基本类型的值如果属性是引用类型拷贝的就是内存地址。即浅拷贝是拷贝一层深层次的引用类型则共享内存地址。常用的方法有object.assgin扩展运算符等等 var a { count: 1, deep: { count: 2 } }; var b Object.assign({}, a); // 或者 var c {...a};// 实现一个浅拷贝 function shallowClone(obj) {const newObj {};for (let prop in obj) {if (obj.hasOwnProperty(prop)) {newObj[prop] obj[prop];}}return newObj }深拷贝开辟一个新的栈两个对象的属性完全相同但是对应两个不同的地址修改一个对象的属性不会改变另一个对象的属性。 /*** 深拷贝* param {Object} obj 要拷贝的对象* param {Map} map 用于存储循环引用对象的地址*/function deepClone(obj {}, map new Map()) {if (obj null) return obj // 如果是null或者undefined我就不进行拷贝操作if (obj instanceof Date) return new Date(obj)if (obj instanceof RegExp) return new RegExp(obj)// 可能是对象或者普通的值 如果是函数的话是不需要深拷贝if (typeof obj ! object) return objif (map.get(obj)) {return map.get(obj);}let result {}; // 初始化返回结果if (obj instanceof Array ||// 加 || 的原因是为了防止 Array 的 prototype 被重写Array.isArray 也是如此Object.prototype.toString(obj) [object Array]) {result [];}// 防止循环引用map.set(obj, result);for (const key in obj) {// 保证 key 不是原型属性if (obj.hasOwnProperty(key)) {// 递归调用result[key] deepClone(obj[key], map);}}return result; }22. 箭头函数的this指向 箭头函数不同于传统JavaScript中的函数箭头函数并没有属于⾃⼰的this它所谓的this是捕获其所在上下⽂的 this 值作为⾃⼰的 this 值并且由于没有属于⾃⼰的this所以是不会被new调⽤的这个所谓的this也不会被改变 23. JavaScript中内存 泄漏的几种情况 内存泄漏一般是指系统进程不再用到的内存没有及时释放造成内存资源浪费导致程序运行速度减慢甚至系统崩溃等严重后果。 全局变量 在局部作用域中函数执行完毕后变量就没有存在的必要了垃圾回收机制很快的做出判断并回收但是对于全局变量很难判断什么时候不用这些变量无法正常回收。所以尽量少使用全局变量使用严格模式在js文件头部或者函数的顶部加上use strict 闭包引起的内存泄露 闭包可以读取函数内部的变量然后让这些变量始终保存在内容中如果在使用结束后没有将局部变量清楚就可能导致内存泄漏。所以将事件处理函数定义在外部解除闭包。 被遗忘的定时器 定时器setInterval、setTimeout不再需要使用时且没有被清除导致定时器的回调函数及其内部依赖的变量都不能被回收造成内存泄漏。所以当不需要定时器的时候调用clearInterval、clearTimeout手动清除 事件监听 垃圾回收机制不好判断事件是否需要被解除导致callback不能被释放此时需要手动解除绑定。及时使用removeEventListener移除事件监听 元素引用没有清除 移除元素后手动设置元素的引用为null console 传递给console.log的对象是不能被垃圾回收可能会存在内存泄漏。所以清除不必要的console 24. 扩展运算符的作用及使用场景 1对象扩展运算符 对象的扩展运算符(…)用于取出参数对象中的所有可遍历属性拷贝到当前对象中。如果用户自定义的属性放在扩展运算符后面则扩展运算符内部的同名属性会被覆盖掉。扩展运算符对对象实例的拷贝属于浅拷贝。 let bar { a: 1, b: 2 }; let baz { ...bar }; // { a: 1, b: 2 } let bas {...bar, ...{a:2, b: 4}}; // {a: 2, b: 4}2数组扩展运算符 数组的扩展运算符可以将一个数组转为用逗号分隔的参数序列且每次只能展开一层数组。 console.log(...[1, 2, 3]); // 1 2 3 console.log(...[1, [2, 3, 4], 5]); // 1 [2, 3, 4] 5function add(x, y) {return x y; } const numbers [1, 2]; add(...numbers) // 3const arr1 [1, 2]; const arr2 [...arr1]; // [1, 2]const arr1 [two, three]; const arr2 [one, ...arr1, four, five]; // [one, two, three, four, five]const [first, ...rest] [1, 2, 3, 4, 5]; console.log(first); // 1 console.log(rest); // [2, 3, 4, 5][...hello] // [ h, e, l, l, o ]const numbers [9, 4, 7, 1]; Math.min(...numbers); // 1 Math.max(...numbers); // 925. 原型与原型链 所有的对象本质上都是通过new 函数创建的包括对象字面量的形式定义对象所有的函数本质上都是通过new Function创建的包括Object、Array等所有的函数都是对象 prototype 每个函数都有一个属性prototype它就是原型默认情况下它是一个普通Object对象这个对象是调用该构造函数所创建的实例的原型 constructor JavaScript同样存在由原型指向构造函数的属性constructor即Func.prototype,constructor -- Func __proto__ 所有对象除了null都具有一个__proto__属性该属性指向该对象的原型 function User() {} var u1 new User(); // u1.__proto__ - User.prototype console.log(u1.__proto__ User.prototype) // truevar u2 new User(); console.log(u1.__proto__ u2.__proto__) // true原型链实例对象在查找属性时如果查找不到就会沿着__proto__去与对象关联的原型上查找如果还查找不到就去找原型的原型直至查到最顶层 原型链指向 所有函数包括Function的__proto__指向Function.prototype 自定义对象实例的__proto__指向构造函数的原型 函数的prototype的__proto__指向Object.prototype Object.prototype.__proto__ -- null 原型修改、重写 function Person(name) {this.name name } // 修改原型 Person.prototype.getName function() {} var p new Person(hello) console.log(p.__proto__ Person.prototype) // true console.log(p.__proto__ p.constructor.prototype) // true // 重写原型 Person.prototype {getName: function() {} } var p new Person(hello) console.log(p.__proto__ Person.prototype) // true console.log(p.__proto__ p.constructor.prototype) // false26. 对闭包的理解 闭包 是一个函数以及其捆绑的周边环境状态词法环境的引用的组合。换而言之闭包让开发者可以从内部函数访问外部函数的作用域。在 JavaScript 中闭包会随着函数的创建而被同时创建。 闭包的应用场景 匿名自执行函数结果缓存封装实现类和继承 闭包的缺点 因为闭包的作用域链会引用包含它的函数的活动对象导致这些活动对象不会被销毁因此会占用更多的内存。 27. 防抖与节流的区别 防抖多次触发事件事件处理函数只执行一次并且是在触发操作结束时执行。也就是说当一个事件被触发准备执行事件函数前会等待一定的时间在这个等待时间内如果没有再次被触发那么就执行如果又触发了那就本次作废重置等待时间直到最终能执行。 主要应用场景搜索框搜索输入用户最后一次输入完再发送请求手机号、邮箱验证输入检测 /*** 防抖函数 n 秒后再执行该事件若在 n 秒内被重复触发则重新计时* param func 要被防抖的函数* param wait 规定的时间*/ function debounce(func, wait) {let timeout null;return function () {let context this; // 保存this指向let args arguments; // 拿到event对象if (timeout) {clearTimeout(timeout);}timeout setTimeout(function () {func.apply(context, args)}, wait)} }节流事件触发后规定时间内事件处理函数不能再次被调用。也就是说在规定的时间内函数只能被调用一次且是最先被触发调用的那次。 主要应用场景高频点击、表单重复提交等。 /*** 节流函数 n 秒内只运行一次若在 n 秒内重复触发只有一次生效* param fn 要被节流的函数* param wait 规定的时间*/ function throttled(fn, wait) {let timer null;return function (...args) {if (!timer) {timer setTimeout(() {fn.apply(this, args);timer null;}, wait);}} }28. 对事件循环Event Loop的理解 Event Loop即事件循环是浏览器或Node解决单线程运行时不会阻塞的一种机制。 JavaScript的确是一门单线程语言但是浏览器UI是多线程的异步任务借助浏览器的线程和JavaScript的执行机制实现。 例如setTimeout就借助浏览器定时器触发线程的计时功能来实现。 浏览器线程 GUI渲染线程 绘制页面解析HTML、CSS构建DOM树等页面的重绘和重排与JS引擎互斥(JS引擎阻塞页面刷新) JS引擎线程 js脚本代码执行负责执行准备好的事件例如定时器计时结束或异步请求成功且正确返回与GUI渲染线程互斥 事件触发线程 当对应的事件满足触发条件将事件添加到js的任务队列末尾多个事件加入任务队列需要排队等待 定时器触发线程 负责执行异步的定时器类事件setTimeout、setInterval等浏览器定时计时由该线程完成计时完毕后将事件添加至任务队列队尾 HTTP请求线程 负责异步请求当监听到异步请求状态变更时如果存在回调函数该线程会将回调函数加入到任务队列队尾 同步与异步执行顺序 JavaScript将任务分为同步任务和异步任务同步任务进入主线中中异步任务首先到Event Table进行回调函数注册。当异步任务的触发条件满足将回调函数从Event Table压入Event Queue中。主线程里面的同步任务执行完毕系统会去Event Queue中读取异步的回调函数。只要主线程空了就会去Event Queue读取回调函数这个过程被称为Event Loop。 宏任务和微任务 JavaScript广义上将任务分为同步任务和异步任务还对异步任务更精细的划分为微任务和宏任务 宏任务包括script脚本的执行、setTimeout、setInterval、setImmediate、AJAX、I/O、history traversalh5当中的历史操作、UI渲染等 微任务Promise.then、Object.observe、process.nextTick(nodejs中的一个异步操作)、MutationObserverh5里面增加的用来监听DOM节点的变化等 Event Loop执行过程 代码开始执行创建一个全局调用栈script作为宏任务执行 执行过程中同步任务立即执行异步任务根据异步任务类型分别注册微任务队列和宏任务队列 同步任务执行完毕查看微任务队列 若存在微任务将微任务队列全部执行包括执行微任务过程中产生新微任务若无微任务查看宏任务队列执行第一个宏任务宏任务执行完毕查看微任务队列重复上述操作直至宏任务队列为空 29. Proxy和Object.defineProperty的区别 代理原理Object.defineProperty的原理是通过将数据属性转变为存取器属性的方式实现的属性读写代理。而Proxy则是因为这个内置的Proxy对象内部有一套监听机制在传入handler对象作为参数构造代理对象后一旦代理对象的某个操作触发就会进入handler中对应注册的处理函数此时我们就可以有选择的使用Reflect将操作转发被代理对象上。 代理局限性Object.defineProperty始终还是局限于属性层面的读写代理对于对象层面以及属性的其它操作代理它都无法实现。鉴于此由于数组对象push、pop等方法的存在它对于数组元素的读写代理实现的并不完全。而使用Proxy则可以很方便的监视数组操作。 自我代理Object.defineProperty方式可以代理到自身代理之后使用对象本身即可也可以代理到别的对象身上代理之后需要使用代理对象。Proxy方式只能代理到Proxy实例对象上。这一点在其它说法中是Proxy对象不需要侵入对象就可以实现代理实际上Object.defineProperty方式也可以不侵入。 30. Ajax、Axios、Fetch的区别 Ajax Ajax是一种创建交互式网页应用的网页开发技术。它是一种在无需重新加载整个网页的情况下能够更新部分网页的技术。通过在后台与服务器进行少量数据交换Ajax可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下对网页的某部分进行更新。传统的网页如果需要更新内容必须重载整个网页页面。 缺点 本身是针对MVC编程不符合前端MVVM的浪潮基于原生XHR开发XHR本身的框架不清晰不符合关注分离的原则配置和调用方式非常混乱而且基于事件的异步模型不友好 Axios Axios是一种基于Promise封装的HTTP客户端 特点 浏览器端发起XMLHttpRequests请求node端发起http请求支持Promise API监听请求和返回对请求和 返回进行转化取消请求自动转换json数据客户端支持抵御XSRF攻击 Fetch Fetch号称是Ajax的替代品是在ES6出现的使用了ES6中的Promise对象。Fetch是基于Promise设计的代码结构比Ajax简单。Fetch不是Ajax的进一步封装而是原生JavaScript没有使用XMLHttpRequest对象。 优点 语法简洁更加语义化基于标准Promise实现支持async/await更加底层提供的API丰富request,response脱离了XHR是ES规范里新的实现方式 缺点 Fetch只对网络请求报错对400、500都当成功的请求服务器返回400、500错误码时并不会reject只有网络错误这些导致请求不能完成时fetch才会被rejectFetch默认不会带cookie需要添加配置项fetch(url, { credentials: include })Fetch不支持abort不支持超时控制使用setTimeout及Promise.reject实现的超时控制并不能阻止请求过程继续在后台运行造成了流量的浪费Fetch没有办法原生监测请求的进度而XHR可以 31. 常见DOM操作 DOM节点获取 getElementById // 按照 id 查询 getElementsByTagName // 按照标签名查询 getElementsByClassName // 按照类名查询 querySelectorAll // 按照 css 选择器查询// 按照 id 查询 var imooc document.getElementById(imooc) // 查询到 id 为 imooc 的元素 // 按照标签名查询 var pList document.getElementsByTagName(p) // 查询到标签为 p 的集合 console.log(divList.length) console.log(divList[0]) // 按照类名查询 var moocList document.getElementsByClassName(mooc) // 查询到类名为 mooc 的集合 // 按照 css 选择器查询 var pList document.querySelectorAll(.mooc) // 查询到类名为 mooc 的集合DOM节点创建 // 首先获取父节点 var container document.getElementById(container) // 创建新节点 var targetSpan document.createElement(span) // 设置 span 节点的内容 targetSpan.innerHTML hello world // 把新创建的元素塞进父节点里去 container.appendChild(targetSpan)DOM节点删除 // 获取目标元素的父元素 var container document.getElementById(container) // 获取目标元素 var targetNode document.getElementById(title) // 删除目标元素 container.removeChild(targetNode)DOM节点修改 // 获取父元素 var container document.getElementById(container) // 获取两个需要被交换的元素 var title document.getElementById(title) var content document.getElementById(content) // 交换两个元素把 content 置于 title 前面 container.insertBefore(content, title)
文章转载自:
http://www.morning.ysnbq.cn.gov.cn.ysnbq.cn
http://www.morning.nmhpq.cn.gov.cn.nmhpq.cn
http://www.morning.hjrjy.cn.gov.cn.hjrjy.cn
http://www.morning.bzcjx.cn.gov.cn.bzcjx.cn
http://www.morning.xnpml.cn.gov.cn.xnpml.cn
http://www.morning.npgwb.cn.gov.cn.npgwb.cn
http://www.morning.nlhcb.cn.gov.cn.nlhcb.cn
http://www.morning.rtspr.cn.gov.cn.rtspr.cn
http://www.morning.bzfld.cn.gov.cn.bzfld.cn
http://www.morning.nkpls.cn.gov.cn.nkpls.cn
http://www.morning.kbqqn.cn.gov.cn.kbqqn.cn
http://www.morning.glnmm.cn.gov.cn.glnmm.cn
http://www.morning.ftnhr.cn.gov.cn.ftnhr.cn
http://www.morning.kaylyea.com.gov.cn.kaylyea.com
http://www.morning.jlgjn.cn.gov.cn.jlgjn.cn
http://www.morning.bgkk.cn.gov.cn.bgkk.cn
http://www.morning.spfq.cn.gov.cn.spfq.cn
http://www.morning.jgncd.cn.gov.cn.jgncd.cn
http://www.morning.rhdqz.cn.gov.cn.rhdqz.cn
http://www.morning.lpcct.cn.gov.cn.lpcct.cn
http://www.morning.lzzqz.cn.gov.cn.lzzqz.cn
http://www.morning.fppzc.cn.gov.cn.fppzc.cn
http://www.morning.kltsn.cn.gov.cn.kltsn.cn
http://www.morning.tznlz.cn.gov.cn.tznlz.cn
http://www.morning.lbbgf.cn.gov.cn.lbbgf.cn
http://www.morning.qnbgk.cn.gov.cn.qnbgk.cn
http://www.morning.ndynz.cn.gov.cn.ndynz.cn
http://www.morning.ypcd.cn.gov.cn.ypcd.cn
http://www.morning.mhdwp.cn.gov.cn.mhdwp.cn
http://www.morning.hnrqn.cn.gov.cn.hnrqn.cn
http://www.morning.zthln.cn.gov.cn.zthln.cn
http://www.morning.lbbrw.cn.gov.cn.lbbrw.cn
http://www.morning.tdwjj.cn.gov.cn.tdwjj.cn
http://www.morning.qmwzz.cn.gov.cn.qmwzz.cn
http://www.morning.hwnnh.cn.gov.cn.hwnnh.cn
http://www.morning.c7498.cn.gov.cn.c7498.cn
http://www.morning.sryyt.cn.gov.cn.sryyt.cn
http://www.morning.lqlc.cn.gov.cn.lqlc.cn
http://www.morning.lthgy.cn.gov.cn.lthgy.cn
http://www.morning.tnhmp.cn.gov.cn.tnhmp.cn
http://www.morning.trqzk.cn.gov.cn.trqzk.cn
http://www.morning.ptqds.cn.gov.cn.ptqds.cn
http://www.morning.dlhxj.cn.gov.cn.dlhxj.cn
http://www.morning.qmzhy.cn.gov.cn.qmzhy.cn
http://www.morning.rpkg.cn.gov.cn.rpkg.cn
http://www.morning.dndk.cn.gov.cn.dndk.cn
http://www.morning.mmzhuti.com.gov.cn.mmzhuti.com
http://www.morning.tmnyj.cn.gov.cn.tmnyj.cn
http://www.morning.ktdqu.cn.gov.cn.ktdqu.cn
http://www.morning.kndyz.cn.gov.cn.kndyz.cn
http://www.morning.langlaitech.cn.gov.cn.langlaitech.cn
http://www.morning.rdbj.cn.gov.cn.rdbj.cn
http://www.morning.bkqw.cn.gov.cn.bkqw.cn
http://www.morning.kndst.cn.gov.cn.kndst.cn
http://www.morning.bsrcr.cn.gov.cn.bsrcr.cn
http://www.morning.fndmk.cn.gov.cn.fndmk.cn
http://www.morning.drnjn.cn.gov.cn.drnjn.cn
http://www.morning.kllzy.com.gov.cn.kllzy.com
http://www.morning.xnkh.cn.gov.cn.xnkh.cn
http://www.morning.wjmb.cn.gov.cn.wjmb.cn
http://www.morning.jtwck.cn.gov.cn.jtwck.cn
http://www.morning.crkmm.cn.gov.cn.crkmm.cn
http://www.morning.lrnfn.cn.gov.cn.lrnfn.cn
http://www.morning.ssqrd.cn.gov.cn.ssqrd.cn
http://www.morning.wddmr.cn.gov.cn.wddmr.cn
http://www.morning.pltbd.cn.gov.cn.pltbd.cn
http://www.morning.ysdwq.cn.gov.cn.ysdwq.cn
http://www.morning.ykkrg.cn.gov.cn.ykkrg.cn
http://www.morning.ghxtk.cn.gov.cn.ghxtk.cn
http://www.morning.gjlxn.cn.gov.cn.gjlxn.cn
http://www.morning.nhlnh.cn.gov.cn.nhlnh.cn
http://www.morning.msbpb.cn.gov.cn.msbpb.cn
http://www.morning.xshkh.cn.gov.cn.xshkh.cn
http://www.morning.yqpzl.cn.gov.cn.yqpzl.cn
http://www.morning.kclkb.cn.gov.cn.kclkb.cn
http://www.morning.rkxdp.cn.gov.cn.rkxdp.cn
http://www.morning.ykrkq.cn.gov.cn.ykrkq.cn
http://www.morning.hydkd.cn.gov.cn.hydkd.cn
http://www.morning.mlffg.cn.gov.cn.mlffg.cn
http://www.morning.htmhl.cn.gov.cn.htmhl.cn
http://www.tj-hxxt.cn/news/271955.html

相关文章:

  • 三亚h5网站定制开发公司动画制作培训学院
  • 做cpa的电影网站模板建设电影网站点击播放是乱页的
  • 门户网站管理建设天津专业做网站的公司有哪些
  • 如何查询网站的备案信息商城小程序介绍
  • 在工商局网站如果做注销公告网站模板怎么设计软件
  • wordpress支付宝打赏海淀区seo全面优化
  • 泉州免费做网站自己做整个网站的流程
  • 成都专业网站制作建设谷德设计网室内设计案例
  • 仿站小工具使用教程中国专门做生鲜的网站
  • 网站建设栏目结构表个人网站有什么用
  • 一个网站怎么做聚合肇庆cms建站系统
  • 怀化人社网站网站速度慢如何做优化
  • 淘客软件自动做网站?白杨seo
  • 国外好的网页设计网站优化网站建设
  • 海南专业网站开发公司广州科技公司有哪些
  • 做网站后台运营这个工作怎么样wordpress付费注册插件
  • 手机网站模板演示网站搭建技术有哪些
  • 手机登录不了建设银行网站wordpress单栏极简
  • 网站备案号 脱离服务商河南零距离文化传播 网站建设
  • 重庆市城市建设档案馆官方网站现在一个天猫店要多少钱
  • 合肥网站推广 公司哪家好抚养网站建设
  • 泉州制作手机网站工程建设与设计期刊网站
  • 郑州企业网站制作南宁网站建公司
  • 自己做电影网站joomla建站教程
  • 池州专业网站建设设计本官方网站案例
  • 郑州营销型网站推广工具网站卖了对方做违法
  • 免费设计海报的网站怎么让百度收录
  • 为什么做网站更新如何做网站推广的策略
  • 申请网站域名空间企业网站的功能主要有
  • 做新闻门户网站需要什么免费的简历模板