DD每周前端七题详解-第六期

    技术2022-07-12  66

    DD每周前端七题详解-第六期

    系列介绍

    你盼世界,我盼望你无bug。Hello 大家好!我是霖呆呆!

    呆呆每周都会分享七道前端题给大家,系列名称就是「DD每周七题」。

    系列的形式主要是:3道JavaScript + 2道HTML + 2道CSS,帮助我们大家一起巩固前端基础。

    所有题目也都会整合至 LinDaiDai/niubility-coding-js 的issues中,欢迎大家提供更好的解题思路,谢谢大家????。

    https://github.com/LinDaiDai/niubility-coding-js/issues

    一起来看看本周的七道题吧。

    正题

    一、[,,,]的长度

    (题目来源:https://github.com/CavsZhouyou/Front-End-Interview-Notebook)

    咋了小伙伴们,感觉这道题目很简单是吗?哈哈,数一数逗号的间隙好像就能得出答案了,比如这样:

    但是这道题的答案并不是4哟,而是3。

    console.log([,,,].length) // 3

    所以最终我们是需要把它想象成这样的:

    也就是最后一个逗号的后面是不算一项的。

    这里其实涉及到了一个名为:尾后逗号的概念,或者说是叫做终止逗号。上面????这道题好像看不出它有什么作用,让我来看看实际上为什么会有这个用法。

    比如现在你的项目中这么一个文件:

    config.js:

    const types = [   {     name: '帅'   },   {     name: '阳光'   }, ] export { types };

    大家可以看到,我在阳光这一项的的后面是多加了一个","的,此时我将这个代码提交到git上并标记为版本1。

    如果这时候types中又要添加一项名为"可爱"的配置项,我只需要在它下面再加上就行了,不需要去改动到原来代码,此时你提交的代码的diff是长这样的:

    const types = [   {     name: '帅'   },   {     name: '阳光'   }, + { +   name: '可爱' + }, ] export { types };

    大家可以看到,只有简单的三行增量代码,如果你没有使用尾后逗号的话,你提交的代码的diff会是这样:

    const types = [   {     name: '帅'   },   {     name: '阳光' - } + }, + { +   name: '可爱' + } ] export { types };

    因此我们可以得出尾后逗号它的作用:

    「使得版本控制更加清晰,以及代码维护麻烦更少。」

    (当然,这种用法在.json后缀的文件中是不能用的哈,因为JSON它严格遵循它自己的语法要求)

    所以回归到这道题中来,像这种使用了多于一个尾后逗号的数组,我们就称之为稀疏数组,稀疏数组它的长度是等于逗号的数量的。

    因此:

    console.log([,,,].length) // 3

    https://github.com/LinDaiDai/niubility-coding-js/issues/37

    二、如何判断当前脚本运行在浏览器还是 node 环境中?

    这道题呆呆其实在很多地方都看到了,但是有的回答好像并不那么靠谱。

    回答这道题首先我们需要知道一个概念:

    浏览器环境:全局对象为window;而在node环境下,是有一个名为global的对象,它的内部Class属性是为"global"。

    内部Class属性也就是我们通过Object.prototype.call(obj)这种方式来获取到的内容,比如:

    console.log(Object.prototype.toString.call([1, 2, 3])); // "[object Array]"

    (关于它的用法呆呆在《【精】从206个console.log()完全弄懂数据类型转换的前世今生(上)》中的toString用法时说的也很详细咯)

    因此我们可以得出这种判断方式:

    var isBrowser = typeof window !== 'undefined'     && ({}).toString.call(window) === '[object Window]'; var isNode = typeof global !== "undefined"     && ({}).toString.call(global) == '[object global]';

    ({}).toString.call()和Object.prototype.toString.call()用法一致,只不过在{}的外面最好加上一个(),也是为了预防JS将大括号{}认为是一个空的代码块(额,呆呆试了一下貌似也没有这方面的问题)。

    https://github.com/LinDaiDai/niubility-coding-js/issues/38

    三、reduce方法有初始值和没有初始值的区别?

    reduce函数的第一个参数是一个回调函数,第二个参数为可选的初始值。

    如果有初始值的话,回调函数就会从数组的第0项开始执行,也就是会执行arr.length次;

    但是如果没有初始值的话,会默认取数组的第0项为初始值,回调函数会从数组的第1项开始执行,也就是会执行arr.length - 1次。

    这点从我们手写一个reduce的实现就可以看出来,代码如下:

    Array.prototype.MyReduce = function (fn, initialValue) {   var arr = Array.prototype.slice.call(this);   var pre, startIndex;   pre = initialValue ? initialValue : arr[0];   startIndex = initialValue ? 0 : 1;   for (var i = startIndex; i < arr.length; i++) {     pre = fn.call(null, pre, arr[i], i, this)   }   return pre }

    过程分析:

    首先,map、reduce这种方法都是数组原型对象上的方法,所以我将MyReduce定义在Array.prototype 上,这样你就可以直接使用ary.MyReduce()这样的方式调用它了(ary是一个类似于这样的数组[1, 2, 3])。

    对于参数,我们参考原生reduce,它接收的第一个参数是一个回调函数,第二个是初始值

    而var arr = ...的作用是获取调用MyReduce函数的那个变量,也就是说this会指向那个变量,例如ary.MyReduce(),那么此时this就为ary。

    至于为什么不使用var arr = this;的方式而是使用Array.prototype.slice.call(this),算是实现一个浅拷贝吧,因为reduce是不会改变原数组的。

    然后就是定义传入reduce中的回调函数的第一个参数pre,也就是上一次运行结果的返回值,可以看到这里就用到了初始值initialValue,如果存在初始值就取初始值,不存在则默认取数组第0项。(当然这里直接用initialValue ?来判断存不存在并不准确,因为我们知道0也会被判断为false)

    接着是定义循环开始的下标startIndex,若是不存在初始值,则初始值是会取数组中的第0项的,相当于第0项并不需要运行,所以startIndex会是1,而如果有初始值的话则需要将数组的每一项都经过fn运行一下。

    最后,for循环中使用fn.call()来调用fn函数,并且最后一个参数是要把原来的数组传递到回调函数中,也就是这里的this。

    https://github.com/LinDaiDai/niubility-coding-js/issues/39

    四、form表单中的label标签的作用?

    label标签不会向用户呈现任何特殊效果,它的作用是为鼠标用户改进了可用性。

    也就是说当你使用了一个label标签和一个input绑定起来之后,点击label标签上的文字就会自动聚焦到input上。

    如下:

    绑定的方式:

    label标签上设置for属性

    input标签上设置和for属性一样的id

    例如:

    <label for="username">username:</label> <input type="text" name="username" id="username"/>

    这里有两点需要注意的:

    这两个标签不一定非要在form标签内才会生效

    for是和id对应的,并不是和name

    https://github.com/LinDaiDai/niubility-coding-js/issues/40

    五、HTML5中的自动完成功能autocomplete是做什么的?

    大家在听到自动完成这个词,会有一点迷糊,自动完成什么?

    其实这个功能的作用是这样的:

    首先,autocomplete是一个属性,这个属性可以设置在form标签上,也可以设置在其它的input标签上。

    被设置了自动完成的标签,会允许浏览器预测对字段的输入。也就是说浏览器会根据你在这个输入框中已经输入过的值,留有一个"历史记录",方便我们下次还想要输入同样的值。

    例如下面这段代码:

    <form autocomplete="on">   testaccount: <input type="text" name="testaccount" /><br />   testpassword: <input type="text" name="testpassword" autocomplete="off" /><br />   <input type="submit" /> </form>

    我把form标签的autocomplete打开,那么这个表单下的所有元素都开启了autocomplete

    接着我把testpassword这一项的autocomplete关闭。

    此时testaccout是有自动完成功能的,而testpassword没有。那么当我们第一次在这两个输入框中输入了内容并提交后。再次点击testaccout输入框,就会出现我们上一次输入并提交的那个值,而点击testpassword时却没有。

    效果如下:

    所以我们来做下总结吧????:

    autocomplete属性规定输入字段是否应该启用自动完成功能;

    它的默认值是启用,也就是"on",另一个值是"off"关闭;

    作用是:允许浏览器预测对字段的输入。当用户在字段开始键入时,浏览器基于之前键入过的值,应该显示出在字段中填写的选项。

    autocomplete 属性适用于<form>,以及下面的 <input> 类型:text, search, url, telephone, email, password, datepickers, range , color。

    https://github.com/LinDaiDai/niubility-coding-js/issues/41

    六、CSS中的visibility有个collapse属性值是干嘛用的?

    visibility会有这么几个个属性值:

    visible

    hidden

    collapse

    inherit

    比较常用的可能是前面两个,用于控制元素的显示隐藏。且我们知道,设置为hidden是会隐藏元素,但是其他元素的布局不改变,相当于此元素变成透明。

    inherit则是从父元素继承visibility属性的值。

    而对于collapse,可能用的不是特别多,我们先来看下它的介绍:

    对于一般的元素,它的表现跟hidden是一样的;

    如果这个元素是table相关的元素,例如table行,table group,table列,table column group,它的表现却跟display: none一样,也就是说,它们占用的空间也会释放。

    下面一起来看看这个案例????:

    html代码:

    <table>   <tr class="tr1">     <td>       tr1     </td>     <td>       tr1     </td>   </tr>   <tr>     <td>       tr2     </td>     <td>       tr2     </td>   </tr> </table>

    css代码:

    table {   border: 1px solid red; } td {   border: 1px solid blue; } .tr1 { }

    我在没给.tr1设置任何属性的时候,页面呈现的效果是这样的,很正常:

    如果设置了visibility: hidden:

    .tr1 {   visibility: hidden; }

    效果如下:

    虽然第一行被隐藏了,但是它的空间还是在的,就像是"隐身"了一样。

    而如果设置了visibility: collapse:

    .tr1 {   visibility: collapse; }

    效果如下:

    最终的效果会和display: none;一样。

    如果你问呆呆这属性有什么实际的用处没有...咳咳,抱歉,好像还真没有????。也可能是呆呆不知道,知道的小伙伴还请提出哟,一起学习一哈。

    https://github.com/LinDaiDai/niubility-coding-js/issues/42

    七、块状元素width:100%与width:auto的区别?

    这两个属性值相信大家都不陌生了,先让我们来看个案例理解一下:

    html代码:

    <div class="super">   <div class="sub1">     我是呆呆的第一个崽   </div>   <div class="sub2">     我是呆呆的第二个崽   </div>   <div class="sub3">     我是呆呆的第三个崽   </div> </div>

    css代码:

    .super {   width: 200px;   height: 100px;   background: skyblue; } .sub1 {   background: #d0e4a9; } .sub2 {   width: 100%;   background: #c077af; } .sub3 {   width: auto;   background: #f8d29d; }

    最开始时,三个崽表现的效果是一样的,并无很大差别:

    此时如果我们对后面两个崽做一下改动:

    .sub2 {   width: 100%;   padding-left: 10px;   margin-left: 10px;   background: #c077af; } .sub3 {   width: auto;   padding-left: 10px;   margin-left: 10px;   background: #f8d29d; }

    给他们都加上左内边距和左外边距,此时的效果就变成了这样:

    大家会发现,设置了width: 100%的崽,它的宽度会和父级的一样,此时如果再给他设置了额外的padding,那它就会比父级还要宽了,也就是会超出父级容器。而因为还设置了margin-left,所以左边也会有一段距离。

    但是设置了width: auto的崽就比较乖了,无论怎样它都不会超出父级,而是选择压缩自己的宽度。

    因此我们可以得出结论:

    两者的计算方式不同(这里的计算规则都是基于box-sizing: content-box;的情况):

    对于width: auto;它的总宽度是等于父宽度的(这里的父宽度是指父级内容的宽度不包括padding、border、margin),即使给元素设置了padding、border、margin等属性,它也会自动分配水平空间。

    对于width: 100%;它表示的是元素内容的宽度等于父宽度,所以它的总宽度是有可能超过父级的,因为如果设置了额外的padding、border,就可能比父级宽了。

    无论是width:100%还是auto,其计算的参照都是父级内容区width值,而非总宽度值,也就是不包括padding、border、margin。

    一般width:auto使用的多一些,因为这样灵活;而width:100%使用比较少,因为在增加padding或者margin的时候,容易使其突破父级框,破坏布局。

    https://github.com/LinDaiDai/niubility-coding-js/issues/43

    参考文章

    知识无价,支持原创。

    参考文章:

    《CSS里的visibility属性有个鲜为人知的属性值:collapse》https://www.webhek.com/post/visibility-collapse.html

    《width:auto和width:100%的区别》https://blog.csdn.net/whaxrl/article/details/47166365

    后语

    你盼世界,我盼望你无bug。这篇文章就介绍到这里。

    您每周也许会花48小时的时间在工作????上,会花49小时的时间在睡觉????上,也许还可以再花20分钟的时间在呆呆的7道题上,日积月累,我相信我们都能见证彼此的成长????。

    什么?你问我为什么系列的名字叫DD?因为呆呆呀,哈哈????。

    喜欢「霖呆呆」的小伙还希望可以关注霖呆呆的公众号 LinDaiDai 或者扫一扫下面的二维码????????????。

    img

    我会不定时的更新一些前端方面的知识内容以及自己的原创文章????

    你的鼓励就是我持续创作的主要动力 ????。

    往期题目可以戳下面????:

    DD每周前端七题详解-第一期https://juejin.im/post/5ece0955e51d45784960ae58

    DD每周前端七题详解-第二期

    DD每周前端七题详解-第三期

    DD每周前端七题详解-第四期

    DD每周前端七题详解-第五期

    或者你也可以查看github上的issues:https://github.com/LinDaiDai/niubility-coding-js/issues

    Processed: 0.015, SQL: 9