范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

前端经典面试题(60道前端面试题包含JSCSSReact浏览器等)

  简答题1、什么是防抖和节流?有什么区别?如何实现?参考答案
  防抖
  触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间 思路:
  每次触发事件时都取消之前的延时调用方法 function debounce(fn) {       let timeout = null; // 创建一个标记用来存放定时器的返回值       return function () {         clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉         timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数           fn.apply(this, arguments);         }, 500);       };     }     function sayHi() {       console.log("防抖成功");     }      var inp = document.getElementById("inp");     inp.addEventListener("input", debounce(sayHi)); // 防抖
  节流
  高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率 思路:
  每次触发事件时都判断当前是否有等待执行的延时函数 function throttle(fn) {       let canRun = true; // 通过闭包保存一个标记       return function () {         if (!canRun) return; // 在函数开头判断标记是否为true,不为true则return         canRun = false; // 立即设置为false         setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中           fn.apply(this, arguments);           // 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return掉           canRun = true;         }, 500);       };     }     function sayHi(e) {       console.log(e.target.innerWidth, e.target.innerHeight);     }     window.addEventListener("resize", throttle(sayHi)); 2、 get请求传参长度的误区、get和post请求在缓存方面的区别
  误区:我们经常说get请求参数的大小存在限制,而post请求的参数大小是无限制的。 参考答案
  实际上HTTP 协议从未规定 GET/POST 的请求长度限制是多少。对get请求参数的限制是来源与浏览器或web服务器,浏览器或web服务器限制了url的长度。为了明确这个概念,我们必须再次强调下面几点: HTTP 协议 未规定 GET 和POST的长度限制 GET的最大长度显示是因为 浏览器和 web服务器限制了 URI的长度 不同的浏览器和WEB服务器,限制的最大长度不一样 要支持IE,则最大长度为2083byte,若只支持Chrome,则最大长度 8182byte
  补充补充一个get和post在缓存方面的区别: get请求类似于查找的过程,用户获取数据,可以不用每次都与数据库连接,所以可以使用缓存。 post不同,post做的一般是修改和删除的工作,所以必须与数据库交互,所以不能使用缓存。因此get请求适合于请求缓存。 3、模块化发展历程
  可从IIFE、AMD、CMD、CommonJS、UMD、webpack(require.ensure)、ES Module、 使用  visibility  替换  display: none  ,因为前者只会引起重绘,后者会引发回流(改变了布局)
  把 DOM 离线后修改,比如:先把 DOM 给  display:none  (有一次 Reflow),然后你修改100次,然后再把它显示出来
  不要把 DOM 结点的属性值放在一个循环里当成循环里的变量for(let i = 0; i < 1000; i++) {// 获取 offsetTop 会导致回流,因为需要去获取正确的值console.log(document.querySelector(".test").style.offsetTop)} 不要使用 table 布局,可能很小的一个小改动会造成整个 table 的重新布局 动画实现的速度的选择,动画速度越快,回流次数越多,也可以选择使用  requestAnimationFrame  CSS 选择符从右往左匹配查找,避免 DOM 深度过深 将频繁运行的动画变为图层,图层能够阻止该节点回流影响别的元素。比如对于  video  标签,浏览器会自动将该节点变为图层。 react、Vue1、写 React / Vue 项目时为什么要在列表组件中写 key,其作用是什么?参考答案
  vue和react都是采用diff算法来对比新旧虚拟节点,从而更新节点。在vue的diff函数中(建议先了解一下diff算法过程)。在交叉对比中,当新节点跟旧节点 头尾交叉对比  没有结果时,会根据新节点的key去对比旧节点数组中的key,从而找到相应旧节点(这里对应的是一个key => index 的map映射)。如果没找到就认为是一个新增节点。而如果没有key,那么就会采用遍历查找的方式去找到对应的旧节点。一种一个map映射,另一种是遍历查找。相比而言。map映射的速度更快。vue部分源码如下: // vue项目  src/core/vdom/patch.js  -488行 // 以下是为了阅读性进行格式化后的代码  // oldCh 是一个旧虚拟节点数组 if (isUndef(oldKeyToIdx)) {   oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx) } if(isDef(newStartVnode.key)) {   // map 方式获取   idxInOld = oldKeyToIdx[newStartVnode.key] } else {   // 遍历方式获取   idxInOld = findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx) }
  创建map函数 function createKeyToOldIdx (children, beginIdx, endIdx) {   let i, key   const map = {}   for (i = beginIdx; i <= endIdx; ++i) {     key = children[i].key     if (isDef(key)) map[key] = i   }   return map }
  遍历寻找 // sameVnode 是对比新旧节点是否相同的函数  function findIdxInOld (node, oldCh, start, end) {     for (let i = start; i < end; i++) {       const c = oldCh[i]              if (isDef(c) && sameVnode(node, c)) return i     }   } 2、React 中 setState 什么时候是同步的,什么时候是异步的?参考答案
  在React中, 如果是由React引发的事件处理(比如通过onClick引发的事件处理),调用setState不会同步更新this.state,除此之外的setState调用会同步执行this.state 。所谓"除此之外",指的是绕过React通过addEventListener直接添加的事件处理函数,还有通过setTimeout/setInterval产生的异步调用。
  **原因:**在React的setState函数实现中,会根据一个变量isBatchingUpdates判断是直接更新this.state还是放到队列中回头再说,而isBatchingUpdates默认是false,也就表示setState会同步更新this.state,但是, 有一个函数batchedUpdates,这个函数会把isBatchingUpdates修改为true,而当React在调用事件处理函数之前就会调用这个batchedUpdates,造成的后果,就是由React控制的事件处理过程setState不会同步更新this.state 。 3、下面输出什么class Example extends React.Component {   constructor() {     super();     this.state = {       val: 0     };   }      componentDidMount() {     this.setState({val: this.state.val + 1});     console.log(this.state.val);    // 第 1 次 log      this.setState({val: this.state.val + 1});     console.log(this.state.val);    // 第 2 次 log      setTimeout(() => {       this.setState({val: this.state.val + 1});       console.log(this.state.val);  // 第 3 次 log        this.setState({val: this.state.val + 1});       console.log(this.state.val);  // 第 4 次 log     }, 0);   }    render() {     return null;   } }; 1、第一次和第二次都是在 react 自身生命周期内,触发时 isBatchingUpdates 为 true,所以并不会直接执行更新 state,而是加入了 dirtyComponents,所以打印时获取的都是更新前的状态 0。  2、两次 setState 时,获取到 this.state.val 都是 0,所以执行时都是将 0 设置成 1,在 react 内部会被合并掉,只执行一次。设置完成后 state.val 值为 1。  3、setTimeout 中的代码,触发时 isBatchingUpdates 为 false,所以能够直接进行更新,所以连着输出 2,3。  输出: 0 0 2 3 4、为什么虚拟dom会提高性能?参考答案
  虚拟dom相当于在js和真实dom中间加了一个缓存,利用dom diff算法避免了没有必要的dom操作,从而提高性能。
  具体实现步骤如下:
  用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中
  当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异
  把2所记录的差异应用到步骤1所构建的真正的DOM树上,视图就更新了。 css1、分析比较 opacity: 0、visibility: hidden、display: none 优劣和适用场景参考答案
  结构:display:none: 会让元素完全从渲染树中消失,渲染的时候不占据任何空间, 不能点击, visibility: hidden:不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,不能点击 opacity: 0: 不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,可以点击
  继承:display: none:是非继承属性,子孙节点消失由于元素从渲染树消失造成,通过修改子孙节点属性无法显示。visibility: hidden:是继承属性,子孙节点消失由于继承了hidden,通过设置visibility: visible;可以让子孙节点显式。
  性能:displaynone : 修改元素会造成文档回流,读屏器不会读取display: none元素内容,性能消耗较大 visibility:hidden: 修改元素只会造成本元素的重绘,性能消耗较少读屏器读取visibility: hidden元素内容 opacity: 0 :修改元素会造成重绘,性能消耗较少
  联系:它们都能让元素不可见 2、清除浮动的方式有哪些?比较好的是哪一种?参考答案
  常用的一般为三种 .clearfix  ,  clear:both  , overflow:hidden  ;
  比较好是  .clearfix  ,伪元素万金油版本,后两者有局限性. .clearfix:after {   visibility: hidden;   display: block;   font-size: 0;   content: " ";   clear: both;   height: 0; }    .clearfix:before, .clearfix:after {     content:"";     display:table; } .clearfix:after{     clear:both;     overflow:hidden; } .clearfix{     zoom:1; }  
  clear:both  :若是用在同一个容器内相邻元素上,那是贼好的,有时候在容器外就有些问题了, 比如相邻容器的包裹层元素塌陷
  overflow:hidden  :这种若是用在同个容器内,可以形成  BFC  避免浮动造成的元素塌陷 4、css sprite 是什么,有什么优缺点参考答案
  概念:将多个小图片拼接到一个图片中。通过 background-position 和元素尺寸调节需要显示的背景图案。
  优点: 减少 HTTP 请求数,极大地提高页面加载速度 增加图片信息重复度,提高压缩比,减少图片大小 更换风格方便,只需在一张或几张图片上修改颜色或样式即可实现
  缺点: 图片合并麻烦 维护麻烦,修改一个图片可能需要重新布局整个图片,样式 5、link与@import的区别参考答案 link  是 HTML 方式,  @import  是 CSS 方式 link  最大限度支持并行下载, @import  过多嵌套导致串行下载,出现FOUC link  可以通过 rel="alternate stylesheet"  指定候选样式 浏览器对 link  支持早于 @import  ,可以使用 @import  对老浏览器隐藏样式 @import  必须在样式规则之前,可以在 css 文件中引用其他文件 总体来说: link 优于@import 6、display: block;和display: inline;的区别参考答案
  block  元素特点:
  1.处于常规流中时,如果 width  没有设置,会自动填充满父容器 2.可以应用 margin/padding   3.在没有设置高度的情况下会扩展高度以包含常规流中的子元素 4.处于常规流中时布局时在前后元素位置之间(独占一个水平空间) 5.忽略 vertical-align
  inline  元素特点
  1.水平方向上根据 direction  依次布局
  2.不会在元素前后进行换行
  3.受 white-space  控制
  4. margin/padding  在竖直方向上无效,水平方向上有效
  5. width/height  属性对非替换行内元素无效,宽度由元素内容决定
  6.非替换行内元素的行框高由 line-height  确定,替换行内元素的行框高由 height  , margin  , padding  , border  决定 7.浮动或绝对定位时会转换为 block  8. vertical-align  属性生效 7、容器包含若干浮动元素时如何清理浮动参考答案 容器元素闭合标签前添加额外元素并设置 clear: both  父元素触发块级格式化上下文(见块级可视化上下文部分) 设置容器元素伪元素进行清理推荐的清理浮动方法 /** * 在标准浏览器下使用 * 1 content内容为空格用于修复opera下文档中出现 *   contenteditable属性时在清理浮动元素上下的空白 * 2 使用display使用table而不是block:可以防止容器和 *   子元素top-margin折叠,这样能使清理效果与BFC,IE6/7 *   zoom: 1;一致 **/  .clearfix:before, .clearfix:after {     content: " "; /* 1 */     display: table; /* 2 */ }  .clearfix:after {     clear: both; }  /** * IE 6/7下使用 * 通过触发hasLayout实现包含浮动 **/ .clearfix {     *zoom: 1; } 8、PNG,GIF,JPG 的区别及如何选参考答案
  GIF : 8 位像素,256 色 无损压缩 支持简单动画 支持 boolean 透明 适合简单动画
  JPEG : 颜色限于 256 有损压缩 可控制压缩质量 不支持透明 适合照片
  PNG : 有 PNG8 和 truecolor PNG PNG8 类似 GIF 颜色上限为 256,文件小,支持 alpha 透明度,无动画 适合图标、背景、按钮 9、display,float,position 的关系参考答案 如果 display  为 none,那么 position 和 float 都不起作用,这种情况下元素不产生框 否则,如果 position 值为 absolute 或者 fixed,框就是绝对定位的,float 的计算值为 none,display 根据下面的表格进行调整。 否则,如果 float 不是 none,框是浮动的,display 根据下表进行调整 否则,如果元素是根元素,display 根据下表进行调整 其他情况下 display 的值为指定值 总结起来: 绝对定位、浮动、根元素都需要调整display 10、如何水平居中一个元素参考答案 如果需要居中的元素为 常规流中 inline 元素 ,为父元素设置 text-align: center;  即可实现 如果需要居中的元素为 常规流中 block 元素 ,1)为元素设置宽度,2)设置左右 margin 为 auto。3)IE6 下需在父元素上设置 text-align: center;  ,再给子元素恢复需要的值
  aaaaaa aaaaaa a a a a a a a a 如果需要居中的元素为 浮动元素 ,1)为元素设置宽度,2) position: relative;  ,3)浮动方向偏移量(left 或者 right)设置为 50%,4)浮动方向上的 margin 设置为元素宽度一半乘以-1
  aaaaaa aaaaaa a a a a a a a a 如果需要居中的元素为 绝对定位元素 ,1)为元素设置宽度,2)偏移量设置为 50%,3)偏移方向外边距设置为元素宽度一半乘以-1
  aaaaaa aaaaaa a a a a a a a a 如果需要居中的元素为 绝对定位元素 ,1)为元素设置宽度,2)设置左右偏移量都为 0,3)设置左右外边距都为 auto
  aaaaaa aaaaaa a a a a a a a a JavaScript1、JS有几种数据类型,其中基本数据类型有哪些?参考答案
  七种数据类型 Boolean Null Undefined Number String Symbol (ECMAScript 6 新定义) Object
  (ES6之前)其中5种为基本类型: string  , number  , boolean  , null  , undefined  ,
  ES6出来的 Symbol  也是原始数据类型 ,表示独一无二的值
  Object  为引用类型(范围挺大),也包括数组、函数, 2、Promise 构造函数是同步执行还是异步执行,那么 then 方法呢?参考答案 const promise = new Promise((resolve, reject) => {   console.log(1)   resolve()   console.log(2) })  promise.then(() => {   console.log(3) })  console.log(4)
  输出结果是: 1 2 4 3 promise构造函数是同步执行的,then方法是异步执行的 Promise new的时候会立即执行里面的代码 then是微任务 会在本次任务执行完的时候执行 setTimeout是宏任务 会在下次任务执行的时候执行 3、JS的四种设计模式参考答案
  工厂模式
  简单的工厂模式可以理解为解决多个相似的问题; function CreatePerson(name,age,sex) {     var obj = new Object();     obj.name = name;     obj.age = age;     obj.sex = sex;     obj.sayName = function(){         return this.name;     }     return obj; } var p1 = new CreatePerson("longen","28","男"); var p2 = new CreatePerson("tugenhua","27","女"); console.log(p1.name); // longen console.log(p1.age);  // 28 console.log(p1.sex);  // 男 console.log(p1.sayName()); // longen  console.log(p2.name);  // tugenhua console.log(p2.age);   // 27 console.log(p2.sex);   // 女 console.log(p2.sayName()); // tugenhua
  单例模式
  只能被实例化(构造函数给实例添加属性与方法)一次 // 单体模式 var Singleton = function(name){     this.name = name; }; Singleton.prototype.getName = function(){     return this.name; } // 获取实例对象 var getInstance = (function() {     var instance = null;     return function(name) {         if(!instance) {//相当于一个一次性阀门,只能实例化一次             instance = new Singleton(name);         }         return instance;     } })(); // 测试单体模式的实例,所以a===b var a = getInstance("aa"); var b = getInstance("bb");
  沙箱模式
  将一些函数放到自执行函数里面,但要用闭包暴露接口,用变量接收暴露的接口,再调用里面的值,否则无法使用里面的值 let sandboxModel=(function(){     function sayName(){};     function sayAge(){};     return{         sayName:sayName,         sayAge:sayAge     } })()
  发布者订阅模式
  就例如如我们关注了某一个公众号,然后他对应的有新的消息就会给你推送, //发布者与订阅模式     var shoeObj = {}; // 定义发布者     shoeObj.list = []; // 缓存列表 存放订阅者回调函数      // 增加订阅者     shoeObj.listen = function(fn) {         shoeObj.list.push(fn); // 订阅消息添加到缓存列表     }      // 发布消息     shoeObj.trigger = function() {             for (var i = 0, fn; fn = this.list[i++];) {                 fn.apply(this, arguments);//第一个参数只是改变fn的this,             }         }      // 小红订阅如下消息     shoeObj.listen(function(color, size) {         console.log("颜色是:" + color);         console.log("尺码是:" + size);     });      // 小花订阅如下消息     shoeObj.listen(function(color, size) {         console.log("再次打印颜色是:" + color);         console.log("再次打印尺码是:" + size);     });     shoeObj.trigger("红色", 40);     shoeObj.trigger("黑色", 42);
  代码实现逻辑是用数组存贮订阅者, 发布者回调函数里面通知的方式是遍历订阅者数组,并将发布者内容传入订阅者数组 4、列举出集中创建实例的方法参考答案
  1.字面量 let obj={"name":"张三"}
  2.Object构造函数创建 let Obj=new Object() Obj.name="张三"
  3.使用工厂模式创建对象 function createPerson(name){  var o = new Object();  o.name = name;  };  return o;  } var person1 = createPerson("张三");
  4.使用构造函数创建对象 function Person(name){  this.name = name; } var person1 = new Person("张三"); 5、简述一下前端事件流参考答案
  HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件onclick、页面的滚动事件onscroll等等,可以向文档或者文档中的元素添加事件侦听器来预订事件。想要知道这些事件是在什么时候进行调用的,就需要了解一下"事件流"的概念。
  什么是事件流:事件流描述的是从页面中接收事件的顺序,DOM2级事件流包括下面几个阶段。 事件捕获阶段 处于目标阶段 事件冒泡阶段
  addEventListener : addEventListener 是DOM2 级事件新增的指定事件处理程序的操作,这个方法接收3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。
  IE只支持事件冒泡 。 6、Function._proto_(getPrototypeOf)是什么?参考答案
  获取一个对象的原型,在chrome中可以通过__proto__的形式,或者在ES6中可以通过Object.getPrototypeOf的形式。
  那么Function.proto是什么么?也就是说Function由什么对象继承而来,我们来做如下判别。 Function.__proto__==Object.prototype //false Function.__proto__==Function.prototype//true
  我们发现Function的原型也是Function。
  我们用图可以来明确这个关系:
  7、简述一下原型 / 构造函数 / 实例参考答案 原型 (prototype)  : 一个简单的对象,用于实现对象的  属性继承 。可以简单的理解成对象的爹。在 Firefox 和 Chrome 中,每个 JavaScript  对象中都包含一个 __proto__  (非标准)的属性指向它爹(该对象的原型),可 obj.__proto__  进行访问。 构造函数: 可以通过 new  来  新建一个对象 的函数。 实例: 通过构造函数和 new  创建出来的对象,便是实例。 实例通过__proto__指向原型,通过constructor指向构造函数 。
  这里来举个栗子,以 Object  为例,我们常用的 Object  便是一个构造函数,因此我们可以通过它构建实例。 // 实例 const instance = new Object()
  则此时,  实例为instance ,  构造函数为Object ,我们知道,构造函数拥有一个 prototype  的属性指向原型,因此原型为: // 原型 const prototype = Object.prototype
  这里我们可以来看出三者的关系: 实例.__proto__ === 原型  原型.constructor === 构造函数  构造函数.prototype === 原型  // 这条线其实是是基于原型进行获取的,可以理解成一条基于原型的映射线 // 例如:  // const o = new Object() // o.constructor === Object   --> true // o.__proto__ = null; // o.constructor === Object   --> false 实例.constructor === 构造函数 8、简述一下JS继承,并举例参考答案
  在 JS 中,继承通常指的便是  原型链继承 ,也就是通过指定原型,并可以通过原型链继承原型上的属性或者方法。 最优化:  圣杯模式
  var inherit = (function(c,p){var F = function(){};return function(c,p){F.prototype = p.prototype;c.prototype = new F();c.uber = p.prototype;c.prototype.constructor = c;}})(); 使用 ES6 的语法糖  class / extends  9、函数柯里化参考答案
  在函数式编程中,函数是一等公民。那么函数柯里化是怎样的呢?
  函数柯里化指的是将能够接收多个参数的函数转化为接收单一参数的函数,并且返回接收余下参数且返回结果的新函数的技术。
  函数柯里化的主要作用和特点就是参数复用、提前返回和延迟执行。
  在一个函数中,首先填充几个参数,然后再返回一个新的函数的技术,称为函数的柯里化。通常可用于在不侵入函数的前提下,为函数  预置通用参数 ,供多次重复调用。 const add = function add(x) {     return function (y) {         return x + y     } }  const add1 = add(1)  add1(2) === 3 add1(20) === 21 10、说说bind、call、apply 区别?参考答案
  call   和  apply   都是为了解决改变  this   的指向。作用都是相同的,只是传参的方式不同。
  除了第一个参数外, call   可以接收一个参数列表, apply   只接受一个参数数组。 let a = {     value: 1 } function getValue(name, age) {     console.log(name)     console.log(age)     console.log(this.value) } getValue.call(a, "yck", "24") getValue.apply(a, ["yck", "24"])
  bind  和其他两个方法作用也是一致的,只是该方法会返回一个函数。并且我们可以通过  bind  实现柯里化。 (下面是对这三个方法的扩展介绍)
  如何实现一个 bind 函数
  对于实现以下几个函数,可以从几个方面思考 不传入第一个参数,那么默认为  window  改变了 this 指向,让新的对象可以执行该函数。那么思路是否可以变成给新的对象添加一个函数,然后在执行完以后删除? Function.prototype.myBind = function (context) {   if (typeof this !== "function") {     throw new TypeError("Error")   }   var _this = this   var args = [...arguments].slice(1)   // 返回一个函数   return function F() {     // 因为返回了一个函数,我们可以 new F(),所以需要判断     if (this instanceof F) {       return new _this(...args, ...arguments)     }     return _this.apply(context, args.concat(...arguments))   } }
  如何实现一个call函数 Function.prototype.myCall = function (context) {   var context = context || window   // 给 context 添加一个属性   // getValue.call(a, "yck", "24") => a.fn = getValue   context.fn = this   // 将 context 后面的参数取出来   var args = [...arguments].slice(1)   // getValue.call(a, "yck", "24") => a.fn("yck", "24")   var result = context.fn(...args)   // 删除 fn   delete context.fn   return result }
  如何实现一个apply函数 Function.prototype.myApply = function (context) {   var context = context || window   context.fn = this    var result   // 需要判断是否存储第二个参数   // 如果存在,就将第二个参数展开   if (arguments[1]) {     result = context.fn(...arguments[1])   } else {     result = context.fn()   }    delete context.fn   return result } 11、箭头函数的特点参考答案 function a() {     return () => {         return () => {             console.log(this)         }     } } console.log(a()()())
  箭头函数其实是没有  this  的,这个函数中的  this  只取决于他外面的第一个不是箭头函数的函数的  this  。在这个例子中,因为调用  a  符合前面代码中的第一个情况,所以  this  是  window  。并且  this  一旦绑定了上下文,就不会被任何代码改变。 程序阅读题1、下面程序输出的结果是什么?function sayHi() {   console.log(name);   console.log(age);   var name = "Lydia";   let age = 21; }  sayHi(); A:  Lydia   和  undefined  B:  Lydia   和  ReferenceError  C:  ReferenceError   和  21  D:  undefined   和  ReferenceError  参考答案
  在函数中,我们首先使用 var  关键字声明了 name  变量。这意味着变量在创建阶段会被提升( JavaScript  会在创建变量创建阶段为其分配内存空间),默认值为 undefined  ,直到我们实际执行到使用该变量的行。我们还没有为 name  变量赋值,所以它仍然保持 undefined  的值。
  使用 let  关键字(和 const  )声明的变量也会存在变量提升,但与 var  不同,初始化没有被提升。在我们声明(初始化)它们之前,它们是不可访问的。这被称为"暂时死区"。当我们在声明变量之前尝试访问变量时, JavaScript  会抛出一个 ReferenceError  。
  关于 let  的是否存在变量提升,我们何以用下面的例子来验证: let name = "ConardLi" {   console.log(name) // Uncaught ReferenceError: name is not defined   let name = "code秘密花园" }
  let  变量如果不存在变量提升, console.log(name)  就会输出 ConardLi  ,结果却抛出了 ReferenceError  ,那么这很好的说明了, let  也存在变量提升,但是它存在一个"暂时死区",在变量未初始化或赋值前不允许访问。
  变量的赋值可以分为三个阶段: 创建变量,在内存中开辟空间 初始化变量,将变量初始化为 undefined  真正赋值
  关于 let  、 var  和 function  : let  的「创建」过程被提升了,但是初始化没有提升。 var  的「创建」和「初始化」都被提升了。 function  的「创建」「初始化」和「赋值」都被提升了。 2、下面代码输出什么var a = 10; (function () {     console.log(a)     a = 5     console.log(window.a)     var a = 20;     console.log(a) })()
  依次输出:undefined -> 10 -> 20 在立即执行函数中,var a = 20; 语句定义了一个局部变量 a,由于js的变量声明提升机制,局部变量a的声明会被提升至立即执行函数的函数体最上方,且由于这样的提升并不包括赋值,因此第一条打印语句会打印undefined,最后一条语句会打印20。  由于变量声明提升,a = 5; 这条语句执行时,局部的变量a已经声明,因此它产生的效果是对局部的变量a赋值,此时window.a 依旧是最开始赋值的10, 3、下面的输出结果是什么?class Chameleon {   static colorChange(newColor) {     this.newColor = newColor;   }    constructor({ newColor = "green" } = {}) {     this.newColor = newColor;   } }  const freddie = new Chameleon({ newColor: "purple" }); freddie.colorChange("orange"); A:  orange  B:  purple  C:  green  D:  TypeError
  答案: D
  colorChange  方法是静态的。静态方法仅在创建它们的构造函数中存在,并且不能传递给任何子级。由于 freddie  是一个子级对象,函数不会传递,所以在 freddie  实例上不存在 freddie  方法:抛出 TypeError  。 4、下面代码中什么时候会输出1?var a = ?; if(a == 1 && a == 2 && a == 3){      conso.log(1); } 参考答案
  因为==会进行隐式类型转换 所以我们重写toString方法就可以了 var a = {   i: 1,   toString() {     return a.i++;   } }  if( a == 1 && a == 2 && a == 3 ) {   console.log(1); } 5、下面的输出结果是什么?var obj = {     "2": 3,     "3": 4,     "length": 2,     "splice": Array.prototype.splice,     "push": Array.prototype.push } obj.push(1) obj.push(2) console.log(obj) 参考答案
  1.使用第一次push,obj对象的push方法设置  obj[2]=1;obj.length+=1  2.使用第二次push,obj对象的push方法设置  obj[3]=2;obj.length+=1  3.使用console.log输出的时候,因为obj具有 length 属性和 splice 方法,故将其作为数组进行打印 4.打印时因为数组未设置下标为 0 1 处的值,故打印为empty,主动 obj[0] 获取为 undefined
  6、下面代码输出的结果是什么?var a = {n: 1}; var b = a; a.x = a = {n: 2};  console.log(a.x)      console.log(b.x) 参考答案
  undefined {n:2}
  首先,a和b同时引用了{n:2}对象,接着执行到a.x = a = {n:2}语句,尽管赋值是从右到左的没错,但是.的优先级比=要高,所以这里首先执行a.x,相当于为a(或者b)所指向的{n:1}对象新增了一个属性x,即此时对象将变为{n:1;x:undefined}。之后按正常情况,从右到左进行赋值,此时执行a ={n:2}的时候,a的引用改变,指向了新对象{n:2},而b依然指向的是旧对象。之后执行a.x = {n:2}的时候,并不会重新解析一遍a,而是沿用最初解析a.x时候的a,也即旧对象,故此时旧对象的x的值为{n:2},旧对象为 {n:1;x:{n:2}},它被b引用着。后面输出a.x的时候,又要解析a了,此时的a是指向新对象的a,而这个新对象是没有x属性的,故访问时输出undefined;而访问b.x的时候,将输出旧对象的x的值,即{n:2}。 7、下面代码的输出是什么?function checkAge(data) {   if (data === { age: 18 }) {     console.log("You are an adult!");   } else if (data == { age: 18 }) {     console.log("You are still an adult.");   } else {     console.log(`Hmm.. You don"t have an age I guess`);   } }  checkAge({ age: 18 }); 参考答案
  Hmm.. You don"t have an age I guess
  在比较相等性,原始类型通过它们的值进行比较,而对象通过它们的引用进行比较。 JavaScript  检查对象是否具有对内存中相同位置的引用。
  我们作为参数传递的对象和我们用于检查相等性的对象在内存中位于不同位置,所以它们的引用是不同的。
  这就是为什么 { age: 18 } === { age: 18 }  和  { age: 18 } == { age: 18 }  返回  false  的原因。 8、下面代码的输出是什么?const obj = { 1: "a", 2: "b", 3: "c" }; const set = new Set([1, 2, 3, 4, 5]);  obj.hasOwnProperty("1"); obj.hasOwnProperty(1); set.has("1"); set.has(1); 参考答案
  true` `true` `false` `true
  所有对象键(不包括 Symbols  )都会被存储为字符串,即使你没有给定字符串类型的键。这就是为什么 obj.hasOwnProperty("1")  也返回 true  。
  上面的说法不适用于 Set  。在我们的 Set  中没有 "1"  : set.has("1")  返回 false  。它有数字类型 1  , set.has(1)  返回 true  。 9、下面代码的输出是什么?// example 1 var a={}, b="123", c=123;   a[b]="b"; a[c]="c";   console.log(a[b]);  --------------------- // example 2 var a={}, b=Symbol("123"), c=Symbol("123");   a[b]="b"; a[c]="c";   console.log(a[b]);  --------------------- // example 3 var a={}, b={key:"123"}, c={key:"456"};   a[b]="b"; a[c]="c";   console.log(a[b]); 参考答案
  这题考察的是对象的键名的转换。 对象的键名只能是字符串和 Symbol 类型。 其他类型的键名会被转换成字符串类型。 对象转字符串默认会调用 toString 方法。 // example 1 var a={}, b="123", c=123; a[b]="b"; // c 的键名会被转换成字符串"123",这里会把 b 覆盖掉。 a[c]="c";   // 输出 c console.log(a[b]);   // example 2 var a={}, b=Symbol("123"), c=Symbol("123");   // b 是 Symbol 类型,不需要转换。 a[b]="b"; // c 是 Symbol 类型,不需要转换。任何一个 Symbol 类型的值都是不相等的,所以不会覆盖掉 b。 a[c]="c"; // 输出 b console.log(a[b]);   // example 3 var a={}, b={key:"123"}, c={key:"456"};   // b 不是字符串也不是 Symbol 类型,需要转换成字符串。 // 对象类型会调用 toString 方法转换成字符串 [object Object]。 a[b]="b"; // c 不是字符串也不是 Symbol 类型,需要转换成字符串。 // 对象类型会调用 toString 方法转换成字符串 [object Object]。这里会把 b 覆盖掉。 a[c]="c";   // 输出 c console.log(a[b]); 10、下面代码的输出是什么?(() => {   let x, y;   try {     throw new Error();   } catch (x) {     (x = 1), (y = 2);     console.log(x);   }   console.log(x);   console.log(y); })(); 参考答案
  1` `undefined` `2
  catch  块接收参数 x  。当我们传递参数时,这与变量的 x  不同。这个变量 x  是属于 catch  作用域的。
  之后,我们将这个块级作用域的变量设置为 1  ,并设置变量 y  的值。现在,我们打印块级作用域的变量 x  ,它等于 1  。
  在 catch  块之外, x  仍然是 undefined  ,而 y  是 2  。当我们想在 catch  块之外的 console.log(x)  时,它返回 undefined  ,而 y  返回 2  。 11、下面代码的输出结果是什么?function Foo() {     Foo.a = function() {         console.log(1)     }     this.a = function() {         console.log(2)     } } Foo.prototype.a = function() {     console.log(3) } Foo.a = function() {     console.log(4) } Foo.a(); let obj = new Foo(); obj.a(); Foo.a(); 参考答案
  输出顺序是 4 2 1 function Foo() {     Foo.a = function() {         console.log(1)     }     this.a = function() {         console.log(2)     } } // 以上只是 Foo 的构建方法,没有产生实例,此刻也没有执行  Foo.prototype.a = function() {     console.log(3) } // 现在在 Foo 上挂载了原型方法 a ,方法输出值为 3  Foo.a = function() {     console.log(4) } // 现在在 Foo 上挂载了直接方法 a ,输出值为 4  Foo.a(); // 立刻执行了 Foo 上的 a 方法,也就是刚刚定义的,所以 // # 输出 4  let obj = new Foo(); /* 这里调用了 Foo 的构建方法。Foo 的构建方法主要做了两件事: 1. 将全局的 Foo 上的直接方法 a 替换为一个输出 1 的方法。 2. 在新对象上挂载直接方法 a ,输出值为 2。 */  obj.a(); // 因为有直接方法 a ,不需要去访问原型链,所以使用的是构建方法里所定义的 this.a, // # 输出 2  Foo.a(); // 构建方法里已经替换了全局 Foo 上的 a 方法,所以 // # 输出 1

痛惜,中科院院士药学家蒋华良突然离世年仅57岁医学界的巨大损失导读在我国有很多高层次人才,比如大家所熟悉的教授工程师专家等,但说到谁的影响力最高,相信很多人会第一时间想到院士。毕竟在我国院士数量稀少,所谓物以稀为贵在这里体现得淋漓尽致。除了本黑灯工厂开启食品生产新时代,多鲜食品智能化全国总部基地在洞泾开建传统食品生产企业如何智造美味生活?日前,伴随着智能化全国总部基地的奠基开工,主打烘焙类食品的多鲜食品有限公司将通过布局黑灯智能生产线,在洞泾镇开启食品生产新时代。该基地位于洞泾镇塘新手妈妈必看!新生儿购买保险容易踩的坑有哪些?摘要新手妈妈在宝宝刚一出生就忙着给宝宝上保险,这能理解,但是没搞清楚这几点之前就投保,难免会陷入一些圈套而不自知,我今天就来系统全面的帮宝妈们梳理一下,希望能够帮助到更多的新手妈妈小红书美妆行业人群洞察报告分析今天从下面3个角度去拆解美妆行业在小红书的地位平台优势与用户价值美妆的种草与被种草美妆个护产品消费洞察注数据来源小红书商业市场部01平台心智与用户价值特点用户心智渠道女性年轻高知消每个人的一生之中,最理想的八大朋友组合成员人是群居动物,人与人之间的来往关系就是互相利用的价值存在的。每个人的朋友圈成员组合直接影响到自身的发展空间。当一个人的朋友圈能包含各行各业的朋友时,人生就能有最大的可能成就化。有人翻阅2022,与书同行,才是普通人最有效提高自我的输入模式翻阅20221hr时间很快,脚步也从未停止眼看又要老一岁了内心也越发觉得不平静了在这个物质横流的世界,我总觉得新一代的年轻人,压力不断增加要急着毕业搞事业,要急着买房,还要买车有存破产那件小事(二)酒是穿肠毒药,色是刮骨钢刀。财是损人利己苗,气是无烟火炮。四件将来合就,相当不久分毫。劝君莫恋最为高,才是修身正道。红尘滚滚,离不开名利二字,自古以来这两个字都没分过家。名利名利,关于国际服部落冲突闪退问题自腾讯接手昆仑代理的部落冲突后有不少脚本号商集体转移国际服开荒因腾讯需要验证QQ或微信号登录才能进入游戏而且无法通过存档的ID文件进行多账号切换顷刻间国际服涌现大量脚本和广告Sup每天坚持做这3个动作,就能藏精气养肾气大家好,我是黄医生。每天做一做这3个动作可以藏精气补肾气,快点来试一试!清风计划超能健康团首先,第一个动作就是踮脚。在八锦缎最后一节叫背后七颠百病消,我们踮脚这个动作就是先用脚把身一汽大众纯电高续航Suv一汽大众ID。6CROZZ于前段时间上市,定位于中大型SUV,这也是一汽大众推出的新能源旗舰SUV,整体尺寸得益于MEB平台短悬长轴的特点,车身长度控制在4891mm,而轴距则是达红米K60pro有五个特别值得期待的看点,估计要比小米13更猛尽管红米K60系列还有两三天才能发布,但是笔者已经迫不及待的搜罗了一下各路大神剧透的消息,然后进行研究对比和筛选,总结出来关于红米K60pro这款手机有五个特别值得期待的看点,如下
法律面前不讲流量网红主播别再心存侥幸来源中国经济网创意图片中国经济网许子杰制作依法纳税是公民的基本义务两位主播一共被追缴罚处9322。56万元,这是迄今为止网络主播偷逃税款的最高额度。今年9月18日,国家税务总局办公帕丽斯希尔顿(ParisHilton)感染NFT,押注ORIGYN融资2000万美元我们专注一级市场,每天发布币圈潜力优势币种,欢迎同好关注。社交名媛帕丽斯希尔顿(ParisHilton)对加密领域产生了浓厚的兴趣,尤其是对不可替代的代币(NFT)。根据新闻稿,希华为P50宝盒精致小巧的折叠屏设计,开合之间满满仪式感近日,华为新品发布会上华为P50Pocket(华为P50宝盒)凭借着强大的实力,成为了当下年轻消费者选购手机的新宠。绚丽夺目的外观和定制化桌面,为消费者带来全新的使用体验,下面我们蚁族崛起以蚂蚁为题材的策略游戏,微观世界的设定很新颖蚁族崛起是一款以蚂蚁为背景题材的策略游戏,2021年8月正式上线,游戏玩法并不难,是一款很消磨时间的休闲游戏。就算你没玩过这一款游戏也不要紧,因为你只要玩过海岛奇兵或部落冲突这两款中国的馒头,陕西有话说中国的馒头在漫漫的旅游途中,人们离不开衣食住行。尤其,当你一天风尘朴朴地一饱眼福地游览中国的名胜古迹,名山大川,恰巧此时,你终会饥肠辘辘,哪怕有个馒头充饥,也会解燃眉之急。当你吃上郑智这支广州队有点意思,中国足球早该这么踢广州队又赢球了!是在恒大出现严重危机,大牌外援离队主教练菜卡跑路的情况下,广州队又赢球了!看这支广州队赢球,我这个中立球迷比看当年恒大亚冠捧杯还舒服,现在的广州队有点意思,中国足球三星大手笔调整高层人事,为甩开中国企业猛追韩国三星电子12月7日发布消息称,领导3个主要部门的3名首席执行官(CEO)将全部撤换。这是该公司4年来首次更换CEO。今后将把智能手机和家电部门合并为产品部门进行一体运营,采用产经济学人全球早报工信部对腾讯采取过渡性行政指导,B站回应自动续费提前3天扣款,长津湖登顶中国影史票房榜工信部对腾讯采取过渡性行政指导据央视新闻消息,今年以来,在工信部开展的App侵害用户权益专项整治中,腾讯公司旗下9款产品存在违规行为,共计4批次被公开通报,违反了2021年信息通信美媒中国超越美国,跃居总财富榜首据彭博社15日报道,美国麦肯锡咨询公司研究部门发布的一份新报告显示,在过去20年中,全球财富增长了两倍,中国领先并超越美国,跃居全球各国财富榜首。据了解,这份报告考察了占全球收入6雪上公主李妮娜,四夺世锦赛冠军,中国雪上项目领军人她曾是自由式滑雪空中技巧项目冠军的垄断者,她是中国自由式滑雪空中技巧项目中诞生的第一个世锦赛冠军,是中国第一个世界杯总决赛冠军的获得者,她还曾是该项目稳居世界排名第一的中国选手,她体育总局国家队严禁所有球员新纹身,已有需自行清除喜欢本频道的别忘了回复三连哦,你的支持是我努力的希望众所周知,现在的国字号球员不仅身体素质和球技与参加过02年韩日世界杯那一代国足球员相比差得太多,拿着高额的年薪不说,他们的白斩鸡