当前位置: 首页 > 后端技术 > Node.js

【步步为营】一周面试题&&答案总结-01

时间:2023-04-03 21:12:56 Node.js

关于【步步为营】一步不及千里。Step-By-Step(点击进入项目)是我在2019-05-20开始的一个项目,项目愿景:循序渐进,量变导致质变。Step-By-Step只会在工作日发布面试题,主要是考虑到部分小伙伴工作比较忙,或者周末有出游的计划。每个周末,我都会仔细阅读大家的答案,并整理出最佳答案。由于本人水平有限,有错误会及时更正。参与者可以相互比较他们的答案。回答问题不是目的。不希望大家简单的搜索答案,复制粘贴到issue下。还有就是希望大家及时查漏补缺/巩固相关知识。更多优质文章可戳:https://github.com/YvetteLau/...1.如何正确判断this的方向?(2019-05-20)如果用一句话来说明this的方向,那就是:谁叫谁,this就指向谁。但仅仅通过这句话,我们往往不能准确判断this的走向。所以我们需要帮助自己一些规则:this的方向可以按照以下顺序判断:1.全局环境浏览器环境中的this:是否在严格模式下,在全局执行环境中(任何函数体之外)this都指向全局对象窗口;node环境:无论是否处于严格模式,在全局执行环境(任何函数体之外),this都是一个空对象{};2.是否是newbinding如果是newbinding,并且构造函数中没有返回函数或对象,则this指向new对象。如下:构造函数的返回值不是函数也不是对象。functionSuper(age){this.age=age;}letinstance=newSuper('26');console.log(instance.age);//26构造函数返回值是函数或对象,本例中this指向返回的对象。functionSuper(age){this.age=age;让obj={a:'2'};returnobj;}letinstance=newSuper('hello');console.log(instance.age);//undefined你可能想知道为什么会这样?我们来看看new的实现原理:创建一个新的对象。这个新对象将通过[[prototype]]连接执行。属性和方法被添加到this引用的对象中。并执行构造函数中的方法。如果函数没有返回其他对象,则this指向这个新对象,否则this指向构造函数中返回的对象。functionnew(func){让target={};target.__proto__=func.prototype;让res=func.call(target);//排除nullif(res&&typeof(res)=="object"||typeof(res)=="function"){returnres;}returntarget;}3.函数是通过call、apply调用,还是通过bind绑定,如果是,则this绑定到指定对象【归结为显式绑定】。functioninfo(){console.log(this.age);}varperson={age:20,info}varage=28;varinfo=person.info;info.call(person);//20info.apply(人);//20info.bind(person)();//20这里还需要注意一个特殊情况,如果call、apply或bind传入的第一个参数值是undefined或null,严格模式下this的值对于传入的值是null/undefined。非严格模式下,实际应用默认绑定规则,this指向全局对象(node环境为global,浏览器环境为window)functioninfo(){//Node环境下:非严格模式global,strictmodeisnull//浏览器环境:非严格模式窗口,严格模式为nullconsole.log(this);console.log(this.age);}varperson={age:20,info}varage=28;varinfo=person.info;//严格模式抛出错误;//非严格模式下输出undefinednode(因为globalage不会挂在global上)//非严格模式。在浏览器环境下,输出28(因为globalage会挂在窗口)info.call(null);4.隐式绑定,函数调用是在一个对象上触发的,即调用处有一个上下文对象。典型的隐式调用是:xxx.fn()functioninfo(){console.log(this.age);}varperson={age:20,info}varage=28;person.info();//20;执行隐式绑定。5.默认绑定,当其他绑定规则无法应用时使用的默认规则,通常是一个独立的函数调用。非严格模式:在node环境下,执行全局对象global;在浏览器环境中,执行全局对象窗口。严格模式:执行undefinedfunctioninfo(){console.log(this.age);}varage=28;//严格模式;throwanerror//非严格模式,node下输出undefined(因为globalage不会挂在global上)//非严格模式。在浏览器环境下,输出28(因为globalage不会挂在window上)//在严格模式下抛出,因为此时this是undefinedinfo();6.在箭头函数的情况下:箭头函数没有自己的this,继承了绑定this的layercontext。让obj={age:20,info:function(){return()=>{console.log(this.age);//this从外部上下文绑定继承this}}}letperson={age:28};letinfo=obj.info();info();//20letinfo2=obj.info.call(person);info2();//28点击查看更多2、JS中的原始类型有多少种?null是一个对象吗?原始数据类型和复杂数据类型有什么区别?(2019-05-21)目前JS中有六种基本类型,分别是:BooleanStringNumberUndefinedNullSymbol(ES6新增)ES10新增了一种基本数据类型:BigInt复杂数据类型只有一种:Objectnull不是对象,虽然typeofnull的输出是object,这是历史遗留下来的问题。JS的初始版本使用的是32位系统。出于性能考虑,使用低阶存储变量的类型信息。000开头的表示是object,null表示全为0,所以错误判断了object。基本数据类型和复杂数据类型的区别在于:栈中存储的内存分配和基本数据类型不同。复杂数据类型存储在堆中,存储在栈中的变量指向堆中的引用地址。访问机制不同。基本数据类型按值访问。复杂数据类型通过引用访问。JS不允许直接访问存储在堆内存中的对象。访问一个对象时,首先得到的是该对象在堆内存中的地址,然后再顺着这个地址得到这个对象中的值。复制变量时不同的(a=b)基本数据类型:a=b;就是将b中保存的原始值的副本赋值给新变量a,a和b完全独立,互不影响复杂数据类型:a=b;将b保存的对象内存的引用地址赋值给新变量a;a和b指向同一个堆内存地址,其中一个值改变,另一个也会改变。letb={age:10}leta=b;a.age=20;console.log(a);//{age:20}不同的(实参/形参)函数参数是根据传值传递的(栈中存储的内容):基本数据类型,复制值;复杂数据类型,复制引用地址//基本数据类型letb=10functionchange(info){info=20;}//info=b;基本数据类型,抄来抄去,两者互不干扰相互change(b);console.log(b);//10//复杂数据类型letb={age:10}functionchange(info){info.age=20;}//info=b;根据第三个区别可以看出,复制的是地址的引用,修改是相互影响的。change(b);console.log(b);//{age:20}点击查看更多3.谈谈你对HTML5语义的理解(2019-05-22)语义就是顾名思义就是HTML5语义指的是合理正确的使用语义标签来创建一个页面结构,比如header、footer、nav,从中可以直观的知道标签的作用,而不是滥用div。语义化的优点是:代码结构清晰,易读,有利于开发和维护,方便其他设备(如屏幕阅读器)解析,根据语义渲染网页。有利于搜索引擎优化(SEO),搜索引擎爬虫会根据不同的标签赋予不同的权重语义标签主要包括:title:主要用于页面头部的信息介绍header:定义文档的头部nav:主要用于对于页面导航main:指定文档的主要内容。对文档应该是唯一的。它不应包含在整个文档中重复出现的内容,例如侧边栏、导航栏、版权信息、站点徽标或搜索表单。article:独立自包含的内容h1~h6:定义标题ul:用于定义无序列表ol:用于定义有序列表address:定义文档或文章作者/所有者的联系方式。canvas:用来绘制图像dialog:定义对话框、确认框或窗口aside:定义其内容之外的内容。