js 随笔二

51 Vue 的响应式原理中 Object.defineProperty 有什么缺陷 C

为什么在 Vue3.0 采用了 Proxy,抛弃了 Object.defineProperty?

  1. Object.defineProperty无法监控到数组下标的变化,导致通过数组下标添加元素,不能实时响应;
  2. Object.defineProperty只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历。Proxy可以劫持整个对象,并返回一个新的对象。
  3. Proxy不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性。

主要是两个,1是数组下标的监听。所以推荐push()等方法进行处理,是对此类方法hack处理。其他的还是有局限性
2、是针对属性进行监听,对于嵌套对象,监听需要迭代循环很多次。性能是个问题。

注释:
Object.defineProperty只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。Vue 2.x里,是通过 递归 + 遍历 data 对象来实现对数据的监控的,如果属性值也是对象那么需要深度遍历,显然如果能劫持一个完整的对象是才是更好的选择。

52 第 52 题:怎么让一个 div 水平垂直居中

果然来了这道题,还是回顾一下比较好:

常见的有绝对定位:
table定位
flex
inline-bock

  1. absolute + margin auto 宽高
  2. absolute + transform 无需
  3. absolut + -margin top 宽高
  4. . absolute+cacl 宽高
  5. flex 无需 移动端推荐
  6. inline-block :after 伪元素实现 兼容性较好
  7. table cell 无需

53 引用类型数据复制操作

var a = {n: 1};
var b = a;
a.x = a = {n: 2};

console.log(a.x) // undefined	 
console.log(b.x) // {n:2}

原因在于连续赋值时, 赋值的顺序是从右边开始到左边的。而且是直接 a = {n: 1}, a.x = {n:1 },而不是 a.x = a 这样去赋值
此时 a 地址已经指向新地址:value为 {n:2}
而b依然指向原地址,所以value为{n:1,x:{n:2}}
参考链接:https://juejin.im/post/5b605473e51d45191a0d81d8#comment

54 实现一个冒泡排序以及如何优化

function bubbleSort(arr) {
    for (let i = 0; i < arr.length; i++) {
        for (let j = 0; j < arr.length - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                const temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
    console.log(arr);
}

// 改进冒泡排序
function bubbleSort1(arr) {
    let i = arr.length - 1;

    while (i > 0) {
        let pos = 0;
        for (let j = 0; j < i; j++) {
            if (arr[j] > arr[j + 1]) {
                pos = j;
                const temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
        i = pos;
    }
    console.log(arr);
}

这都写错,哈哈,只考虑和后一位比,没想到后面可能还有,需要一直比下去。

时间复杂度O(n^2) 两次循环嘛毕竟。
冒泡待改进的地方:也就是每次比较之后,可能会重新比较一遍。
那么可能优化的点就是,不满足判断条件的可以记录一下,直接进入相关之后的下标进行比较。

实现就是上面那个了,自己手写下也可以。

55 数组操作

某公司 1 到 12 月份的销售额存在一个对象里面
如下:{1:222, 2:123, 5:888},请把数据处理为如下结构:[222, 123, null, null, 888, null, null, null, null, null, null, null]。

es6 数组方便,忘记了map 这个用法了

function main(obj){
    var arr = Array.from({length:12})
    return arr.map((it,i)=>{
        return obj[i+1] || null
    })
}

原本的做法:

function main(obj){
    var arr = []
    for(var i = 1;i<13;i++){
            arr.push(obj[i] || null)
    }    
    return arr
}

56 实现链式调用和事件队列 sleep函数 C

目标:

LazyMan('Tony');
// Hi I am Tony

LazyMan('Tony').sleep(10).eat('lunch');
// Hi I am Tony
// 等待了10秒...
// I am eating lunch

LazyMan('Tony').eat('lunch').sleep(10).eat('dinner');
// Hi I am Tony
// I am eating lunch
// 等待了10秒...
// I am eating diner

LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
// Hi I am Tony
// 等待了5秒...
// I am eating lunch
// I am eating dinner
// 等待了10秒...
// I am eating junk food

没见过,一时没想起来,整体是利用时间队列,按顺序执行,遇到sleep,则延时。实现挺好的

class LazyManClass {
    constructor(name) {
        this.taskList = [];
        this.name = name;
        console.log(`Hi I am ${this.name}`);
        setTimeout(() => {
            this.next();
        }, 0);
    }
    eat (name) {
        var that = this;
        var fn = (function (n) {
            return function () {
                console.log(`I am eating ${n}`)
                that.next();
            }
        })(name);
        this.taskList.push(fn);
        return this;
    }
    sleepFirst (time) {
        var that = this;
        var fn = (function (t) {
            return function () {
                setTimeout(() => {
                    console.log(`等待了${t}秒...`)
                    that.next();
                }, t * 1000);  
            }
        })(time);
        this.taskList.unshift(fn);
        return this;
    }
    sleep (time) {
        var that = this
        var fn = (function (t) {
            return function () {
                setTimeout(() => {
                    console.log(`等待了${t}秒...`)
                    that.next();
                }, t * 1000); 
            }
        })(time);
        this.taskList.push(fn);
        return this;
    }
    next () {
        var fn = this.taskList.shift();
        fn && fn();
    }
}
function LazyMan(name) {
    return new LazyManClass(name);
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(4).eat('junk food');

57 分析比较 opacity: 0、visibility: hidden、display: none 优劣和适用场景。 C

opacity: 0 占文档流,颜色透明而已,可点击
visibility: hidden, 占据空间,不能点击
display:none 元素不存在,不可点击

如果祖先元素遭遇某祸害,则其子孙孙无一例外也要遭殃,比如:
opacity:0和display:none,若父节点元素应用了opacity:0和display:none,无论其子孙元素如何挣扎都不会再出现在大众视野;
而若父节点元素应用visibility:hidden,子孙元素应用visibility:visible,那么其就会毫无意外的显现出来。

58 箭头函数与普通函数(function)的区别是什么?构造函数(function)可以使用 new 生成实例,那么箭头函数可以吗?为什么?

区别在于
箭头函数,上下文在定义时确定,而普通函数在运行时确定。
所以箭头函数对于改变上下文的方法均不适用,例如call,apply,bind等

可以说是箭头函数没有this,继承于上层作用域,
没有 prototype 属性,即指向 undefined

对于new显然也不能

补充另外两点:
2、不可以使用 arguments 对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

3、不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数。

多个参考吧:

  • 箭头函数没有 this,它会从自己的作用域链的上一层继承 this(因此无法使用 apply / call / bind 进行绑定 this 值);
  • 不绑定 arguments,当在箭头函数中调用 aruguments 时同样会向作用域链中查询结果;
  • 不绑定 super 和 new.target;
  • 没有 prototype 属性,即指向 undefined;
  • 无法使用 new 实例化对象,因为普通构造函数通过 new 实例化对象时 this 指向实例对象,而箭头函数没有 this 值,同时 箭头函数也没有 prototype。

59 求数组交集 C

nums1 = [1, 2, 2, 1],nums2 = [2, 2],返回 [2, 2]

比较粗暴的就是循环,从第一位开始判断是否另一个函数是否存在,否则继续下一位,是则拼接。 显然不能用这种方式了。

还是最长公共子序列的问题

const intersect = (nums1, nums2) => {
  const map = {}
  const res = []
  for (let n of nums1) {
    if (map[n]) {
      map[n]++
    } else {
      map[n] = 1
    }
  }
  for (let n of nums2) {
    if (map[n] > 0) {
      res.push(n)
      map[n]--
    }
  }
  return res
}

利用数组来存放第一个数组出现次数,然后第二个数组来遍历,去对象中查找,如果出现数字则当前元素放入。
不考虑顺序可以

下面的解释比较详细:
这道题不是工程题,是道算法题。求的是两个数组的最长公共子序列 (子序列要求顺序,交集不需要)。所以上面用一个filter一个includes或者indexOf的都是错的。

反例很简单。

var nums1 = [1]
var nums2 = [1,1]
或者

var nums1 = [1,1]
var nums2 = [1]
交集应该是[1]

跑一下你们的方法就能知道错了。

这道题两种思路,空间换时间,或者不用额外空间就提升时间复杂度。

空间换时间的思路是用个Hash表来存数组1的元素以及出现的个数(此处需要遍历n次,并存一个n级别的空间)。
遍历数组2,发现数组2里有Hash表里的值就存到Result数组里,并把Hash表内该值次数减一(为0之后就Delete)。如果不存在Hash表里,就跳过。这样时间复杂度就是(m+n)

不用额外空间,就用遍历n的时候,判断值在不在m里,如果在,把m里的该值push到Result数组里,并将该值从m数组里删掉(用splice)。这样就是不用额外空间,但是提高了时间复杂度。

60 css 已知如下代码,如何修改才能让图片宽度为 300px ?注意下面代码不可修改。 C

<img src="1.jpg" style="width:480px!important;”>

1、js 来设置style
2、看css的优先级,css 内联,写死好像不行的。

css相关,主要就是集中于 其他属性来限制,width是不能怎么着它了
1、缩放 transform: scale(0.625);
2、 zoom 也可行zoom:0.5

设置最大宽度:
3、max-width:300

利用box-sizing 的特性,设置padding,宽度不变有padding依然会撑开
4、 box-sizing: border-box; padding-left:90px; padding-right: 90px

61 如何实现token加密 C 如何加密 就是生成随机数然后加密,加密算法?

jwt举例:
需要一个secret(随机数)
后端利用secret和加密算法(如:HMAC-SHA256)对payload(如账号密码)生成一个字符串(token),返回前端
前端每次request在header中带上token
后端用同样的算法解密

62 redux 为什么要把 reducer 设计成纯函数 需要斟酌语言

因为redux 单向数据流的特性,reducer 承担的职责就是更新数据,然后 同步给 store,此外还要承担时间旅行等职责。
避免在reducer中其他操作的副作用。

比较长和形象的回答:
首先命题应当改一下,中文有歧义,可能改为 “redux中的reducer为什么必须(最好)是纯函数“,我想表达的意思是,redux没有强制你reducer是个纯函数,事实上,没有人能通过框架限制判断一个函数是否是纯函数,所以题目中的'设计成'这个短语貌似在说redux已经把reducer强制规定是纯函数了。这回让你怀疑你对redux的认知。

正文如下
然后说一下为什么reducer最好是纯函数,首先你得看看文档怎么说reducer的作用的,‘接收旧的 state 和 action,返回新的 state’,您可得瞧好咯,他就是起一个对数据做简单处理后返回state的作用,为什么只起这个作用,这时用设计这个词回答这个问题才恰当,因为redux把reducer设计成只负责这个作用。很白痴的问答对吧,所以题目的答案也就简单了,reducer的职责不允许有副作用,副作用简单来说就是不确定性,如果reducer有副作用,那么返回的state就不确定,举个例子,你的reducer就做了一个value = value + 1这个逻辑,然后返回state为{value},ok,这个过程太jr纯了,然后你可能觉得要加个请求来取得value后再加1,那么你的逻辑就是value = getValue() + 1, getValue是个请求函数,返回一个值,这种情况,退一万步讲,如果你的网络请求这次出错,那么getValue就返回的不是一个数值,value就不确定了,所以return的state你也不确定了,前端UI拿到的数据也不确定了,所以就是这个环节引入了副作用,他娘的redux设计好的规范就被你破坏了,redux就没卵用了。到此为止这个问题回答完了,我没有说什么上面几个jr说的教科书的理论,甚至还加了些脏话。请原谅,这只是戏剧需要。

最后我回答下如何解决这个副作用,实际上也很白痴的问题,这里的请求可以放在reducer之前,你先请求,该做出错处理的就做出错处理,等拿到实际数据后在发送action来调用reducer。这样通过前移副作用的方式,使reducer变得纯洁。

63 模拟实现一个Promis.finally

该方法就是无论状态如何,最后都会调用,并且将值返回,所以内部就是执行直接then来响应

Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value  => P.resolve(callback()).then(() => value),
    reason => P.resolve(callback()).then(() => { throw reason })
  );
};

64 如何设计实现无缝轮播 C

思路呢,重点在于无缝了,当运行到最后一个元素的时候,

克隆第一张和最后一张作为过渡

看别人实现吧,自己确实没实现过:
最简单的方法就是复制一个轮播的元素,当复制元素将要滚到目标位置后,把原来的元素进行归位的操作,以达到无缝的轮播效果。

当焦点位于图片1时,如果再往前滚的话,整个队列会被拉倒真正的第五张图。至于真正的图片1前面的副本图片5只是让用户产生视觉差,从而不会让用户明显感觉到图片被倒向了图片5,看起来就像时无缝轮播。

可以参考链接:https://github.com/Youszz/baidu_2017_frontEnd_study/blob/master/tooltrips/idnex2.html

其实目的还是从头移动到了尾部,只是让其不这么突兀罢了,在显示的时候移动,看起来还是同张照片。

参考:https://github.com/Youszz/baidu_2017_frontEnd_study/blob/master/tooltrips/idnex2.html

65 a.b.c.d 和 a['b']['c']['d'],哪个性能更高

先说个人理解,这两种都是常见的使用方式,一个是类似数组形式,一个是直接字符串,后一个存在一个解析变量的过程

66 ES6 代码转成 ES5 代码的实现思路是什么

不就是babel的实现思路吗,首先词法分析,得到词法树,然后根据特性进行转换,生成最初代码。

比较正规一点的说法:

解析:解析代码字符串,生成 AST;
转换:按一定的规则转换、修改 AST;
生成:将修改后的 AST 转换成普通代码。

将代码字符串解析成抽象语法树,即所谓的 AST
对 AST 进行处理,在这个阶段可以对 ES6 代码进行相应转换,即转成 ES5 代码
根据处理后的 AST 再生成代码字符串

67 编程,将数组排序并分成子数组

随机生成一个长度为 10 的整数类型的数组,例如 [2, 10, 3, 4, 5, 11, 10, 11, 20],将其排列成一个新数组,要求新数组形式如下,例如 [[2, 3, 4, 5], [10, 11], [20]]。

思路: 首先sort 排序,然后将连续元素合并

function main(arr){
    let res = [],
        t = []
    arr.sort((a,b)=>{
        return a-b
    })
    // 去重
    let temp = [...new Set(arr)]
    // 归类,是按照连续还是大小呢
    temp.forEach((it,i)=>{
        t.push(it)
        // 连续截断  如果不等于后一位,则放入当前数组
        if(++it!= temp[i+1]){
            res.push(t)
            // 清空t,以存放下一位
            t = []
        }
    })
    return res
}

生成随机数

function randomArray(length = 10, max = 100) {
  return Array.from({ length }, () => ~~(Math.random() * max))
}

68 1px问题

transform
background-image

整体的:
1 伪元素 + transform scaleY(.5)
2 border-image
3 background-image
4 box-shadow

69 大小写转换

例如 如何把一个字符串的大小写取反(大写变小写小写变大写),例如 ’AbC' 变成 'aBc'

下面这个比较巧妙,需要学习,1是直接map得到新的数组,2是跟大写比较是否相等来判断当前状态

function main(str){
    var arr = str.split('');
    var new_arr = arr.map((item) => {
    
        return item === item.toUpperCase() ? item.toLowerCase() : item.toUpperCase();
    });
    return new_arr.join('');
}

70 webpack 热更新原理 C

HMR 原来有看过呢,就是监听文件变化,然后使用node

1.当修改了一个或多个文件;
2.文件系统接收更改并通知webpack;
3.webpack重新编译构建一个或多个模块,并通知HMR服务器进行更新;
4.HMR Server 使用webSocket通知HMR runtime 需要更新,HMR运行时通过HTTP请求更新jsonp;
5.HMR运行时替换更新中的模块,如果确定这些模块无法更新,则触发整个页面刷新。

71 字符匹配算法 C

从长度为 n 的字符串 S 中,查找是否存在字符串 T,T 的长度是 m,若存在返回所在位置。

KMP算法,不过没看明白。直接用indexOf显然犯规了哈哈

const find = (S, T) => {
  if (S.length < T.length) return -1
  // 从0开始截取字符串之后进行对比,不匹配就继续往下走。
  for (let i = 0; i < S.length; i++) {
    if (S.slice(i, i + T.length) === T) return i
  }
  return -1
}

或者说是indexOf的底层实现
参考链接:https://note.youdao.com/ynoteshare1/index.html?id=91749237e787b4aa0b246336ea0c1137&type=note

实现代码:

var S, T;
var next = [];

// 预计算next数组
function getNext() {
        let k = -1,
                j = 0;
        next[0] = -1;
        while (j &lt; len_t) {
                if (k == -1 || T[j] == T[k]) {
                        ++j;
                        ++k;
                        next[j] = k;
                } else k = next[k];
        }
}

// 返回子串首次出现的位置
function KMP_Index() //T是模式串,S是 主串 
{
        let i = 0,
                j = 0;
        getNext();
        while (j &lt; len_t &amp;&amp; i &lt; len_s) {
                if (j == -1 || T[j] == S[i]) {
                        i++;
                        j++;
                } else j = next[j];
        }
        if (j == len_t) {
                return i - len_t;
        } else return -1;
}

//返回子串出现的次数
function KMP_Count() {
        let ans = 0;
        let i = 0,
                j = 0;

        getNext();
        for (i = 0; i &lt; len_s; i++) {
                while (j ]]> 0 &amp;&amp; T[j] != S[i]) {
                        j = next[j];
                }
                if (T[j] == S[i]) j++;
                if (j == len_t) {
                        ans++;
                        j = next[j];
                }
        }
        return ans;
}

S = "123454321";
T = "0"
len_s = S.length;
len_t = T.length;

//KMP_Index()如果为-1则没有匹配
console.log(`主串为${S},模式串为${T},模式串首次出现的位置为${KMP_Index()},出现的次数为${KMP_Count()}`);
![101a36edff1a1945e89a081471342b91.png](evernotecid://9AD03560-32E8-422A-AA45-8A86202B7517/appyinxiangcom/15863714/ENResource/p174)
var S, T;
var next = [];

// 预计算next数组
function getNext() {
        let k = -1,
                j = 0;
        next[0] = -1;
        while (j &lt; len_t) {
                if (k == -1 || T[j] == T[k]) {
                        ++j;
                        ++k;
                        next[j] = k;
                } else k = next[k];
        }
}

// 返回子串首次出现的位置
function KMP_Index() //T是模式串,S是 主串 
{
        let i = 0,
                j = 0;
        getNext();
        while (j &lt; len_t &amp;&amp; i &lt; len_s) {
                if (j == -1 || T[j] == S[i]) {
                        i++;
                        j++;
                } else j = next[j];
        }
        if (j == len_t) {
                return i - len_t;
        } else return -1;
}

//返回子串出现的次数
function KMP_Count() {
        let ans = 0;
        let i = 0,
                j = 0;

        getNext();
        for (i = 0; i &lt; len_s; i++) {
                while (j ]]> 0 &amp;&amp; T[j] != S[i]) {
                        j = next[j];
                }
                if (T[j] == S[i]) j++;
                if (j == len_t) {
                        ans++;
                        j = next[j];
                }
        }
        return ans;
}

S = "123454321";
T = "0"
len_s = S.length;
len_t = T.length;

//KMP_Index()如果为-1则没有匹配
console.log(`主串为${S},模式串为${T},模式串首次出现的位置为${KMP_Index()},出现的次数为${KMP_Count()}`);

72 为什么普通 for 循环的性能远远高于 forEach 的性能,请解释其中的原因。

因为forEach 作为高阶函数,其回调会产生作用域上下文等开销,不如for

补充L:
forEach里操作了toObject 以及判断是否终止循环条件 比for loop 复杂一点

73 介绍下 BFC、IFC、GFC 和 FFC C

卧槽,只知道第一个了。。。
BFC 块级格式内容 当触发该属性时,元素以block形式呈现,所以会用以清除浮动。

BFC(Block formatting contexts):块级格式上下文
页面上的一个隔离的渲染区域,那么他是如何产生的呢?可以触发BFC的元素有float、position、overflow、display:table-cell/ inline-block/table-caption ;BFC有什么作用呢?比如说实现多栏布局’

IFC(Inline formatting contexts):内联格式上下文
IFC的line box(线框)高度由其包含行内元素中最高的实际高度计算而来(不受到竖直方向的padding/margin影响)IFC中的line box一般左右都贴紧整个IFC,但是会因为float元素而扰乱。float元素会位于IFC与与line box之间,使得line box宽度缩短。 同个ifc下的多个line box高度会不同
IFC中时不可能有块级元素的,当插入块级元素时(如p中插入div)会产生两个匿名块与div分隔开,即产生两个IFC,每个IFC对外表现为块级元素,与div垂直排列。
那么IFC一般有什么用呢?
水平居中:当一个块要在环境中水平居中时,设置其为inline-block则会在外层产生IFC,通过text-align则可以使其水平居中。
垂直居中:创建一个IFC,用其中一个元素撑开父元素的高度,然后设置其vertical-align:middle,其他行内元素则可以在此父元素下垂直居中。

GFC(GrideLayout formatting contexts):网格布局格式化上下文
当为一个元素设置display值为grid的时候,此元素将会获得一个独立的渲染区域,我们可以通过在网格容器(grid container)上定义网格定义行(grid definition rows)和网格定义列(grid definition columns)属性各在网格项目(grid item)上定义网格行(grid row)和网格列(grid columns)为每一个网格项目(grid item)定义位置和空间。那么GFC有什么用呢,和table又有什么区别呢?首先同样是一个二维的表格,但GridLayout会有更加丰富的属性来控制行列,控制对齐以及更为精细的渲染语义和控制。

FFC(Flex formatting contexts):自适应格式上下文
display值为flex或者inline-flex的元素将会生成自适应容器(flex container),可惜这个牛逼的属性只有谷歌和火狐支持,不过在移动端也足够了,至少safari和chrome还是OK的,毕竟这俩在移动端才是王道。Flex Box 由伸缩容器和伸缩项目组成。通过设置元素的 display 属性为 flex 或 inline-flex 可以得到一个伸缩容器。设置为 flex 的容器被渲染为一个块级元素,而设置为 inline-flex 的容器则渲染为一个行内元素。伸缩容器中的每一个子元素都是一个伸缩项目。伸缩项目可以是任意数量的。伸缩容器外和伸缩项目内的一切元素都不受影响。简单地说,Flexbox 定义了伸缩容器内伸缩项目该如何布局。

参考链接:https://www.cnblogs.com/dingyufenglian/p/4845477.html

74 使用 JavaScript Proxy 实现简单的数据绑定 C proxy的用法还不太熟练

proxy 用法:

var obj = new Proxy({}, {
  get: function (target, key, receiver) {
    console.log(`getting ${key}!`);
    return Reflect.get(target, key, receiver);
  },
  set: function (target, key, value, receiver) {
    console.log(`setting ${key}!`);
    return Reflect.set(target, key, value, receiver);
  }
});

参考es6内容L学习吧:reflect : http://es6.ruanyifeng.com/#docs/reflect

答案参考:https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/123

75 数组里面有10万个数据,取第一个元素和第10万个元素的时间相差多少

这个是考察数组底层存放的,数组是链表,确实没什么差别。

数组可以直接根据索引取的对应的元素,所以不管取哪个位置的元素的时间复杂度都是 O(1)

JavaScript 没有真正意义上的数组,所有的数组其实是对象,其“索引”看起来是数字,其实会被转换成字符串,作为属性名(对象的 key)来使用。所以无论是取第 1 个还是取第 10 万个元素,都是用 key 精确查找哈希表的过程,其消耗时间大致相同。

不管如何存储,index差别不大

Chrome 浏览器JS引擎 V8中,数组有两种存储模式,一种是类似C语言中的线性结构存储(索引值连续,且都是正整数的情况下),一种是采用Hash结构存储(索引值为负数,数组稀疏,间隔比较大

76 引用类型数据的操作问题 C

var b = {key:1} a[b] = 'c'
主要是key为引用数据类型时,此时默认toString() 为 [object Object] 所以对象a为{[object Object]: "c"}

// example 1
var a={}, b='123', c=123;  
a[b]='b';
a[c]='c';  
console.log(a[b]); // c

---------------------
// example 2
var a={}, b=Symbol('123'), c=Symbol('123');  
a[b]='b';
a[c]='c';  
console.log(a[b]); //b

---------------------
// example 3
var a={}, b={key:'123'}, c={key:'456'};  
a[b]='b';
a[c]='c';  
console.log(a[b]); // c   

---------------------
// example 4 引申一个隐式转换
var a={}, b={toString:()=>'c',key:'123'}, c={toString:()=>'b',key:'456'};  
a[b]='b';
a[c]='c';  
console.log(a.b); // c

77 算法题「旋转数组」 C

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。

输入: [1, 2, 3, 4, 5, 6, 7] 和 k = 3
输出: [5, 6, 7, 1, 2, 3, 4]
解释:
向右旋转 1 步: [7, 1, 2, 3, 4, 5, 6]
向右旋转 2 步: [6, 7, 1, 2, 3, 4, 5]
向右旋转 3 步: [5, 6, 7, 1, 2, 3, 4]
输入: [-1, -100, 3, 99] 和 k = 2
输出: [3, 99, -1, -100]
解释: 
向右旋转 1 步: [99, -1, -100, 3]
向右旋转 2 步: [3, 99, -1, -100]

function main(arr,num){
    // 为避免超出长度还是要取余
    var k = num%arr.length
    // 取出后几位,合并数组
    var len = arr.length
    var tem = arr.splice(len - k, k)
    return [...tem,...arr]
}

注意下取余数,不然超过数组长度有些问题

78 Vue 的父组件和子组件生命周期钩子执行顺序是什么

应该和react 类似,render之前的父优先,之后的子优先,其实就是洋葱模型

看下比较系统的答案:
加载渲染过程
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
子组件更新过程
父beforeUpdate->子beforeUpdate->子updated->父updated
父组件更新过程
父beforeUpdate->父updated
销毁过程
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

79 input 搜索如何防抖,如何处理中文输入 C

防抖就是 常规防抖的输入了吧
中文输入的问题暂时没有考虑过 参考:https://segmentfault.com/a/1190000012490380

80 介绍下 Promise.all 使用、原理实现及错误处理

使用就是对多个promise 按顺序输出执行结果,

原理,我想一想。。 对传入的promise 再构造一个 ,then之后加个回调,假如事件队列,如果队列长度满足,则返回。。。

这个思路还是对的: 仅供参考

all(list) {
        return new Promise((resolve, reject) => {
            let resValues = [];
            let counts = 0;
            for (let [i, p] of list) {
                resolve(p).then(res => {
                    counts++;
                    resValues[i] = res;
                    if (counts === list.length) {
                        resolve(resValues)
                    }
                }, err => {
                    reject(err)
                })
            }
        })
    }

81 打印出 1 - 10000 之间的所有对称数

function main(){
   // 最小两位
   for(var i=10;i<1001;i++){
       var num = i + ''
       var nums = num.split('').reverse().join('')
       if (nums == num ) {
         console.log(i)
       } 
   }
}
posted @ 2019-08-13 11:16  潇湘待雨  阅读(230)  评论(0编辑  收藏  举报