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

DD每周七题-第一期

系列介绍

你盼世界,我盼望你无bug。Hello 你们好!我是霖呆呆!前端

从这周起呆呆每周都会分享七道前端题给你们,系列名称就是「DD每周七题」。git

系列的形式主要是:3道JavaScript + 2道HTML + 2道CSS,帮助咱们你们一块儿巩固前端基础。github

全部题目也都会整合至 LinDaiDai/niubility-coding-jsissues中,欢迎你们提供更好的解题思路,谢谢你们😁。web

正题

1、Array(3)和Array(3, 4)的区别?

console.log(Array(3))
console.log(Array(3, 4))  console.log(new Array(3)) console.log(new Array(3, 4))  console.log(Array.of(3)) console.log(Array.of(3, 4)) 复制代码

考察知识点:数组

  • Array()new Array()
  • Array()参数个数不一样时的不一样表现
  • Array.of()的做用

结果:浏览器

console.log(Array(3)) // [empty x 3]
console.log(Array(3, 4)) // [3, 4]  console.log(new Array(3)) // [empty x 3] console.log(new Array(3, 4)) // [3, 4]  console.log(Array.of(3)) // [3] console.log(Array.of(3, 4)) // [3, 4] 复制代码

总结:编辑器

  • Array使不使用 new效果都是同样的
  • Array方法,若是参数是一位的话,这个参数表示的是数组的长度,并建立此长度的空数组
  • Array方法,若是参数是多位的话则每个参数都是数组的一项,会按顺序返回数组
  • Array.of()接收任意个参数,将按顺序成为返回数组中的元素,并返回这个新数组。

github.com/LinDaiDai/n…函数

2、请建立一个长度为100,值为对应下标的数组

// cool点的写法:
[...Array(100).keys()]  // 其余方法: Array(100).join(",").split(",").map((v, i) => i) Array(100).fill().map((v, i) => i) 复制代码

后面两种方法相信你们都能看到懂,也没啥好说的了😄,让咱们仔细看一下这个比较cool的写法:ui

  • 使用Array(100)建立一个内容全为empty的数组:[empty x 100]this

  • 使用keys()方法从数组建立一个包含数组键的可迭代对象:

    可迭代对象是否是让你想到了generator,没错的,这里的keys()Array.prototype上的方法,你们可能会把它和咱们以前用的比较多的Object.keys()搞混。

    说一下它的做用吧,它其实就像刚刚介绍的同样,会建立一个可迭代对象,那么小伙伴们应该知道,一个可迭代对象返回的数据会是这样的:

    { value: 0, done: false }
    复制代码

    value为此次的返回值,done为当前可迭代对象的逻辑块是否执行完成。

    因此你会看到如下这段代码是会这样执行的:

    let it = Array(100).keys()
    console.log(it.next) // {value: 0, done: false} console.log(it.next) // {value: 1, done: false} console.log(it.next) // {value: 2, done: false} console.log(it.next) // {value: 3, done: false} 复制代码
  • 至于[...arr]这个就是ES6的写法了,转化为数组,固然你也能够直接用Array.from()。这两种方式都支持将可迭代对象转换为数组。

github.com/LinDaiDai/n…

3、实现 arr[-1] = arr[arr.length - 1]

这道题的意思是:提供一个createArr()方法,用此方法建立的数组知足arr[-1] = arr[arr.length - 1]

function createArr (...elements) {
 // ...代码  return arr } var arr1 = createArr(1, 2, 3) console.log(arr1[-1]) // 3 console.log(arr1[-2]) // 2 复制代码

解题思路:

其实对于这类题目,我首先想到的会是Object.defineProperty()或者Proxy。由于这里涉及到了对数组值的获取,显然用Proxy是比较合适的。什么?你问我为何不用Object.defineProperty()?由于这个方法是针对于对象的某一个属性的呀,对数组来讲不合适。

因此对于这道题,咱们也许可使用Proxy代理每次传入进来的下标,也就是重写一下数组的get方法,在这个方法中咱们去处理这方面的逻辑,一块儿来看看代码吧😊:

function createArr (...elements) {
 let handler = {  get (target, key, receiver) { // 第三个参数传不传均可以  let index = Number(key) // 或者 let index = ~~key  if (index < 0) {  index = String(target.length + index)  }  return Reflect.get(target, index, receiver)  }  }  let target = [...elements] // 建立一个新数组  return new Proxy(target, handler) } var arr1 = createArr(1, 2, 3) console.log(arr1[-1]) // 3 console.log(arr1[-2]) // 2 复制代码

注意点:

  • get接收到的第二个参数key表示的是数组下标,它是字符串形式,因此须要转为Number,固然方法有不少种了,使用Number()也能够,使用~~双非按位取反运算符也能够。对比于Number()的好处就是Number(undefined)会转换为NaN;可是使用~~能保证一直是数字,~~undefined === 0。(什么?你还不知道区别?那你得看霖呆呆的这篇文章了:JS中按位取反运算符~及其它运算符)

  • 接下来只须要判断一下传入进来的下标是否是小于0的,小于0的话加上数组的长度就能够了

  • 而后返回index这一项使用的是Reflect.get(target, index)。什么?为何不直接用target[index]?固然这样也能够,对比target[index]的区别就是Reflect.get(target, index)若是传入的target不是一个Object的话(数组也属于对象),就会报一个类型错误TypeError,而target[index]返回的会是一个undefined。好比这样:

    var obj = 5
    console.log(obj['b']) // undefined console.log(Reflect.get(obj, 'b')) // Uncaught TypeError: Reflect.get called on non-object 复制代码

扩展点:

呆呆这边主要是想扩展一下get的第三个参数receiver(接受者),在MDN上的解释是:

若是target对象中指定了getterreceiver则为getter调用时的this值。

来看个例子理解一下😊。

案例一

例如咱们开始有这么一个对象:

var obj = {
 fn: function () {  console.log('lindaidai')  } } 复制代码

如今使用Proxy来赋值到obj1中:

var obj = {
 fn: function () {  console.log('lindaidai')  } } var obj1 = new Proxy(obj, {  get (target, key, receiver) {  console.log(receiver === obj1) // true  console.log(receiver === target) // false  return target[key]  } }) obj1.fn() 复制代码

能够看到,receiver表示的是obj1这个新的代理对象,target表示的是被代理的对象obj

因此,receiver能够表示使用代理对象自己

案例二

另外一种状况,receiver也能够表示是从其继承的对象

var proxy = new Proxy({}, {
 get (target, key, receiver) {  return receiver;  } }) console.log(proxy.getReceiver === proxy) // true var inherits = Object.create(proxy) console.log(inherits.getReceiver === inherits) // true 复制代码

这个案例中,我新建了一个空对象的代理对象proxy,使用proxy.getReceiver获取它的receiver,发现它就是代理对象自己。

而若是我将这个代理对象做为一个原型对象,建立出一个新的对象inherits,也就是实现了原型式继承,那么这时候receiver的值就是这个被继承的对象inherits

总结

  • 可使用 Proxy代理,来改变每次获取数组的值。
  • Proxyget中,第二个参数是字符串,即便传入的是数组下标。
  • 对比于 Number()的好处就是 Number(undefined)会转换为 NaN;可是使用 ~~能保证一直是数字, ~~undefined === 0
  • 对比 target[index]的区别就是 Reflect.get(target, index)若是传入的 target不是一个 Object的话(数组也属于对象),就会报一个类型错误 TypeError,而 target[index]返回的会是一个 undefined
  • Proxyget中,第三个参数 receiver一般为使用代理对象自己或从其继承的对象。

github.com/LinDaiDai/n…

4、addEventListener和attachEvent的区别?

  • 前者是标准浏览器中的用法,后者 IE8如下
  • addEventListener可有冒泡,可有捕获; attachEvent只有冒泡,没有捕获。
  • 前者事件名不带 on,后者带 on
  • 前者回调函数中的 this指向当前元素,后者指向 window

github.com/LinDaiDai/n…

5、addEventListener函数的第三个参数

第三个参数涉及到冒泡和捕获,是true时为捕获,是false则为冒泡。

或者是一个对象{passive: true},针对的是Safari浏览器,禁止/开启使用滚动的时候要用到。

github.com/LinDaiDai/n…

6、文字单超出显示省略号

div {
 width: 200px;  overflow: hidden;  white-space: nowrap;  text-overflow: ellipsis; } 复制代码

github.com/LinDaiDai/n…

7、文字多行超出显示省略号

div {
 width: 200px;  display: -webkit-box;  -webkit-box-orient: vertical;  -webkit-line-clamp: 3;  overflow: hidden; } 复制代码

该方法适用于WebKit浏览器及移动端。

跨浏览器兼容方案:

p {
 position:relative;  line-height:1.4em;  /* 3 times the line-height to show 3 lines */  height:4.2em;  overflow:hidden; } p::after {  content:"...";  font-weight:bold;  position:absolute;  bottom:0;  right:0;  padding:0 20px 1px 45px; } 复制代码

github.com/LinDaiDai/n…

后语

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

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

什么?你问我为何系列的名字叫DD?由于呆呆呀,哈哈😄。

喜欢霖呆呆的小伙还但愿能够关注霖呆呆的公众号 LinDaiDai 或者扫一扫下面的二维码👇👇👇。

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

你的鼓励就是我持续创做的主要动力 😊。

本文使用 mdnice 排版

相关文章
相关标签/搜索