前端总结(后续不断更新)

1,
reflow和repaint:回流和重绘。
回流:renderTree 重建。
重绘:外观样式风格进行更新。(color更改)
页面在第一次加载时候必须进行了回流操作,有回流一定伴随重绘,但是重绘不一定回流。
减少回流和重绘,也就是减少对renderTree的操作:
合并多次多DOM的修改
2,
浏览器对页面的呈现流程基本如下:
1)浏览器把获取到的html代码解析成一个DOM树,每个tag都是树上的一个节点,根节点就是document对象,包括(display:none,和js动态创建的节点)
2)浏览器把所有样式解析成样式结构体(定义的和代理的所有样式),不同浏览器会自动去掉不能识别的样式。
3)DOM Tree 和样式结构体合并生成 RenderTree,每个节点都有style,不包含隐藏的节点(display:none),但是包含不可见的节点(visibility:hidden)。
4)浏览器根据RenderTree 绘制页面
3,
内存泄漏
对于持续运行的服务进程,必须及时释放不再用到的内存,不然内存会越来越多,导致进程越来越慢,甚至系统崩溃。
不用到的内存没有及时释放,就叫内存泄漏。
垃圾回收机制:引用计数法。如果一个值的引用次数为0,则证明不再使用,可以释放。如果引用次数不为0,却不再使用,无法释放,导致了内存泄漏。
如何检测是否存在:谷歌控制台---memory--timeline
原因:
1)全局变量(可以在js文件开头‘use strict’,严格解析,阻止意外的全局变量产生)
2)没有及时清理定时器
3)闭包
4)超出DOM的引用
4,

const--let.png

const 只声明,不赋值会报错;一旦赋值,就不能修改,否则也报错,不存在变量提升,常量
let 块级作用域,不能重复声明,不存在变量提升
var 函数作用域,可以重复声明
5,
三列布局,两边定宽,中间自适应
1)

wrap包裹.png

position-margin.png

2)


布局.png
float-margin.png

3)


布局.png
flex.png

6,
两列布局,左边定宽,右边自适应
1)

float--BFC.png

2)
position--margin.png

7,
flex
传统布局:display+position+float解决方案。
flex布局的元素称为容器,元素内的子元素称为容器的项目。项目默认沿着主轴排序。
image.png

设置为flex布局后,子元素的float,vertical-align,clear属性失效。
容器属性:

flex-direction: 
      row(默认)
      row-reverse(主轴为水平方向,起点在右端)
      column(主轴为垂直方向,起点在上沿)
      column-reverse(主轴为垂直方向,起点在下沿)
flex-wrap:
        nowrap(默认)/
        wrap(主轴方向换行)/
        wrap-reverse(换行第一行在最下边)
flex-flow: flex-direction | flex-wrap(以上两种简写)
在主轴方向:
justify-content: 
        flex-start(左对齐)/
        flex-end(右对齐)/
        center(居中)/
        space-between(间隔相等,最左最右对齐)/
        space-around(每个项目左右相等)
在交叉轴上:
align-items: 
        flex-start(上对齐)/
        flex-end(下对齐)/
        center(居中)/
        baseline(基线对齐)/
        stretch(若项目没设置高度,则占满整个容器高度)
align-content: 多条主轴时候起作用
        flex-start(上对齐)/
        flex-end(下对齐)/
        center(居中)/
        space-between(间隔相等,上下对齐)/
        space-around(每个主轴上下相等)
        stretch(轴线占满整个交叉轴)

项目属性:

order:数值(越小越靠前;默认是0)
flex-grow:放大倍数(默认是0)容器存在剩余空间时候才会生效。有放大属性的项目会根据比例平分剩余空间。
 <div class="box">
        <div style="height: 100px;background:red;flex-grow:2">12</div>
        <div style="height: 20px;background:red;flex-grow:1">123</div>
        <div style="height: 30px;background:red;flex-grow:1">1234</div>
        <div style="height: 120px;background:red;">12345</div>
        <div style="height: 60px;background:red;">123456</div>
      </div>

image.png

flex-shrink: (默认是1)缩小倍数 。容器空间不足才会生效。有放大属性的项目会根据比例缩小不够的空间。属性为0,其他项目都为1,则空间不足时,前者不缩小

 <div class="box">
        <div style="height: 100px;background:red;flex-shrink: 0">12</div>
        <div style="height: 20px;background:red;flex-shrink: 0">123</div>
        <div style="height: 30px;background:red;flex-shrink: 2">1234</div>
        <div style="height: 120px;background:red;flex-shrink: 1">12345</div>
        <div style="height: 60px;background:red;flex-shrink: 1">123456</div>
      </div>
image.png

flex:0/1/auto(简写)

align-self:  可覆盖父元素的align-items。
        auto(继承父元素的align-items)/
        flex-start
        flex-end
        baseline
        stretch

8,
垂直水平居中

margin.png
transform.png

margin2.png

9,
position
absolute:最近的positioned的祖先元素,如果祖先都没有positioned,相对于body
relative:偏移正常位置,其他元素不受影响
fixed:固定定位,即使滚动页面,也不会改变相对浏览器窗口的位置
static:默认值,没有positioned
10,
分析输入URL到页面被返回的过程:
1)输入地址
2)浏览器查询IP地址(DNS查找:浏览器缓存--系统缓存--路由缓存--递归搜索)
3)浏览器给web服务器发送一个http请求
4)服务器给浏览器返回一个永久重定向301(有利于搜素引擎SEO,两个地址都看作同一个地址,增加了访问量;增强缓存友好性)
5)浏览器跟踪从定向的地址,继续发送另一个请求
6)服务器处理请求
7)服务器返回200的反应
8)浏览器显示HTML
9)浏览器发送获取嵌入在HTML中的对象的请求(静态文件资源)
10)浏览器发送异步ajax请求(页面显示完成后,浏览器仍与服务器连接)
11,
变量提升:只提升声明,不提升赋值

var a = 2;
function A() {
      var a = 1;
      console.log(a);//1
      console.log(this.a)//2
}
function B() {
      var a = 4;
      return A;
}
B()();

12,
DNS又称域名系统,用来解析可读主机名(www.baidu.com)为机器可读的IP地址(204.13.248.115)
DNS是如何工作的:
1)本地DNS缓存查询,如果未查到结果,则进行第二步骤;
2)计算机联系ISP(网络服务提供商)的递归DNS服务器,执行DNS查询;如果未查询到,进行第三步骤;
3)询问根域名服务器,(从右向左),将请求指向(.com)对应的顶级域服务器(TLD.com),继续检查下一个信息(baidu),并将查询指向负责此域名的服务器。这些权威的服务器将信息存储在DNS中。
4)递归服务器从权威服务器获取到记录,并存在本地缓存中。(记录都是有有效期的)
5)返回计算机
13,
webStorage和cookie
cookie:存储量4KB左右,比webStorage存储小,且方式不直观
webStorage:
localStorage:本地永久存储,除非主动删除,不然不会消除;
sessionStorage:浏览器页面打开中会存在,关闭页面,数据消失;
API:setItem(),getItem(),removeItem(),clear(),addEventListener()
14,
跨域问题
js语言安全机制--同源策略(同一协议,同一域名,同一端口号)引起的跨域问题。
解决方案:
1)jsonp实现跨域
动态创建script标签,src属性值为 跨域地址+传入的数据+回调函数。执行完之后再动态删除之前创建的script.

jsonp.png

2)H5的postMessage(message,targetOrigin)
向其他window对象发送message,通过监听其他对象message事件,来获取传过来的信息。
postMessage.png

3)document.domain
试用情况:主域相同,子域不同的情况;通过控制iframe
document.png

15,
获取url的指定参数:
字符串切割.png

16,
事件监听
事件流:捕获型事件(从外向内)和冒泡型事件(从内向外)
使用‘return false’阻止默认行为(提交按钮,超链接)
1)绑定HTML元素上
image.png

2)绑定到DOM上
image.png

3)addEvent:可以添加多个事件
image.png

17,
前端性能优化
content方面:
1)减少HTTP请求(CSS Sprites,合并多个CSS文件和js文件)
2)减少DNS查找(主流浏览器都是有自己独有的缓存,而不是操作系统的;一个网站最少2个域,但不多余四个)
3)使用AJAX缓存
4)延迟加载组件,预加载组件
5)减少DOM节点数量
6)最小化Iframe的数量
server方面:
1)使用内容分发网络(CDN)(网站内容分散到多个CDN,处在不同地域位置的访问下载速度快)
2)使用Etag(判断浏览器缓存和服务器的原始内容是否匹配)
3)对Ajax请求用Get
cookie方面:
1)减少cookie大小
Css方面
1)避免使用css表达式
2)使用link代提import
3)放在head中
图片方面:
1)优化图片大小
2)通过CSS Sprites整合图片
JS方面:
1)减少对DOM的操作
2)js和CSS文件外部引入
3)放在页面底部
18,
promise
函数回调成功:
resolve.png

函数回调失败:
then语法两个参数--成功和失败.png

catch语法:(和失败语法意义相同)
image.png

不同点:
出错可以继续执行.png

19,
js单线程,执行完主线程,浏览器维护一个任务队列task queue;主线程的任务执行完,去task queue中拿最先放进queue的task放到主线程,循环反复event loops

macro-task: script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering
micro-task: process.nextTick, 原生Promise, Object.observe, MutationObserver
在执行完主线程的任务后,会去看micro-task队列,把所有任务依次执行,之后再去看macro-task队列。

image.png

20,
js模块化的发展历程
第一阶段:无模块化
一个JS文件相当于一个模块,引入多个JS文件
第二阶段:CommonJS规范
起初是用在node端的,前端的webpack也支持原生CommonJS的。
通过require方法同步加载所需要依赖的模块,然后通过module.exports或者exports导出对外暴露的接口,解决了全局变量污染的问题。

注意:因为module.exports本身就是一个对象,所以,我们在导出时可以使用 module.exports = {foo: 'bar'} 和 module.exports.foo = 'bar'。但是, exports 是 module.exports 的一个引用,或者理解为exports是一个指针,exports指向module.exports,这样,我们就只能使用 exports.foo = 'bar' 的方式,而不能使用exports = {foo: 'bar'}这种方式,因为exports = {foo: 'bar'}这种方式的使用就会导致exports指向了别的对象。

第三阶段:AMD规范
非同步加载模块,实现是require.js。适合浏览器端。异步加载,依赖前置。
requrie([module],callback)//引用模块
define('id',[depends],callback)//定义模块
第四阶段:CMD规范
按需加载,依赖就近,同样实现了浏览器端的模块化加载。sea.js

AMD---CMD.png

第五阶段:ES6模块化
import导入---export导出
21,
js中数组方法:
forEach:让数组中每个item做一件事(例如:输出item);
map:让数组中每个item进行某种运算,返回新数组(例如:*2);
filter:选出符合条件的item,组合成新数组(例如:>4);
reduce:数组中前后两项进行相应操作,返回最终结果(例如:相乘);
every:数组中 所有item都满足条件才会返回true;
some:只要有一个满足条件,就返回true;
image.png

22,
数组去重
ES6:
image.png

ES5:
image.png

reduce.png

23,

转义符.png

24,
box-sizing:content-box
标准盒子总宽度 = margin + border + padding + content(width)
W3C标准盒模型.png

IE盒子总宽度 = margin + width(margin + padding + border)
box-sizing:border-box
怪异盒模型.png

***background填充padding
绝对定位不包含border.png

25,
vue数据双向绑定原理及实现
1,对数据劫持监听
Obj.defineProperty()监听所有属性是否变化,给属性设置set函数,当数据改变了就会触发set函数。读取的时候触发get函数。
2,结合发布者-订阅者模式
通知变化给订阅者(watcher),订阅者看是否需要更新。同时需要一个指令解析器(compile),扫描解析每个元素节点,根据相关指令初始化成一个订阅者,并且替换模板数据或者绑定更新函数。
发布者-订阅者模式.png

26,
DOM,Jquery,React
DOM:文档对应的对象模型;
jQuery和react都是库。
jQuery是一个JS库,开发者使用它直接和DOM进行沟通。
React:给开发者和DOM直接建立了联系。他的三项核心技术:
1)响应式UI
2)虚拟DOM
3)组件
27,
this 在js中的使用
this .png

28,
斐波那契数列
数列.png

29,
增加原生字符串方法
字符串重复次数方法.png

30,
同字母异序(两个字符串,由相同字母组成,字母顺序可以不同)
比较.png

31,
CSS3属性
CSS3 2D转换:

  1. translate(50px,100px)平移
  2. rotate(30deg) 旋转
  3. scale(2,4) 放大或缩小
  4. skew(30deg,30deg) 翻转

CSS3 3D转换:

  1. translateX/Y/Z平移
  2. rotateX/Y/Z 旋转
  3. scaleX/Y/Z 放大或缩小

CSS3过渡
transition : width 2s liner 2s(CSS属性、持续时间、动画曲线、开始时间)

CSS3动画

@keyframes myfirstdiv {
  from{ background:yellow}
  to{background:green}
}

或者

@keyframes myfirstdiv
{
    0%   {background: red;}
    25%  {background: yellow;}
    50%  {background: blue;}
    100% {background: green;}
}
animation: myfirstdiv 5s

32,
css hack手段
解决浏览器兼容问题,跨平台应用
1)IE条件注释法

IE条件注释法.png

2)css属性前缀法


属性前缀.png

3)选择器前缀法

选择器前缀.png

33,
var 重复声明
var.png

var可以重复声明,如果重复声明的一个变量有初始值,那就相当于复制语句;如果没有初始值,则对之前声明不会有任何影响.
34,
js继承
1)
原型链.png

2)
构造.png

3)
实例.png

4)
组合.png

5)
寄生组合.png

35,
判断一个数组是数组
1)instanceof
arr instanceof Array//true
2)constructor
arr.constructor === Array //true
arr._ _proto_ _.constructor === Array //true
instanceof 和constructor 判断的变量,必须在当前页面声明的,比如,一个页面(父页面)有一个框架,框架中引用了一个页面(子页面),在子页面中声明了一个ary,并将其赋值给父页面的一个变量,这时判断该变量,Array == object.constructor;会返回false;
原因:
1、array属于引用型数据,在传递过程中,仅仅是引用地址的传递。
2、每个页面的Array原生对象所引用的地址是不一样的,在子页面声明的array,所对应的构造函数,是子页面的Array对象;父页面来进行判断,使用的Array并不等于子页面的Array;切记,不然很难跟踪问题!
3) Object.prototype.toString.call(a) //[object Array]
4 ) Array.isArray(arr) //true
36,
回文字符串判断
回文.png

37,
解决for循环输出最后一个值的问题
JS单线程原因,后调用setTimeout,此时for循环已经执行完了
闭包.png

38,
npm install react --save
npm install安装所有依赖
webpack 进行打包
babel-loader 把ES6转换成ES5
loader.png

webpack dev server 搭建本地服务器;自动刷新
node server 把app挂载到本地服务器上
webpack dev serve --hot --inline 要想让HMR生效,就要在应用热替换模块或者根模块加入允许热替换的代码

jQuery 事件驱动。用户点击button,派发事件,根据事件更新操作UI
react 数据驱动。会把数据映射到UI上,不用管UI。核心思想就是模块化组件化。
数据:state(组件本身的数据)和props(其他组件传入的数据)
第一次加载组件涉及到的组件生命周期顺序:

image.png

image.png

react-router:
      browserHistory: baidu.com/a/b
      hashHistory: baidu.com/#a/b
react-router组件: 装载页面的组件,把组件传给他来展示页面
      indexRoute:第一次进入系统,没有存入URL的时候
      Route
页面切换的时候组件会被销毁,所以根据需求把相应功能放在根组件里。
事件订阅:全局事件管理器,发布事件操作,只要订阅事件的部分,就会监听到事件,做事件处理。
virtual Dom : 存储DOM信息的数据结构,存在内存当中,也就是JS对象中,能够完整描述DOM的结构。
DOM Diff:对比两个virtual Dom ,数据更新的时候会生成新的virtual Dom 。
image.png

解决方案:immutable
组件间通信方式:
1、事件回调,
2、事件订阅(缺乏统一管理),
3、redux(统一对系统事件的管理)
39,
ES6解构赋值
image.png

变量名必须和属性名一致,node.name的值存给了变量名为name的变量。
40,
new四部曲
1.首先在内存堆上开辟一个空间存储对象
2.this会指向实例也就是指向当前对象
3.设置属性和方法,执行代码块
4.返回实例,也就是当前对象
41,
重排序数组
image.png

42,
image.png

浅拷贝和深拷贝
浅拷贝:两个对象同时指向一个引用地址,一个修改,其他也跟着变。地址存放在栈中。数据在堆中。

数组浅copy.png

深拷贝:
1.单层对象,没有嵌套


对象深copy方法一.png

对象深copy方法二.png
ES6扩展运算符.png

克隆数组.png
//数组深拷贝
var arr2 = arr.slice(0);
var arr3 = arr.concat();

2.多层嵌套(以上三种 方法不好使了)
JSON对象的parse和stringify

const newObj = JSON.parse(JSON.stringify(oldObj));

JSON字符串反序列化成JS对象,stringify方法可以将JS对象序列化成JSON字符串,

// 构造函数
function person(pname) {
  this.name = pname;
}
const Messi = new person('Messi');
// 函数
function say() {
  console.log('hi');
};
const oldObj = {
  a: say,
  b: new Array(1),
  c: new RegExp('ab+c', 'i'),
  d: Messi
};
const newObj = JSON.parse(JSON.stringify(oldObj));
console.log(newObj.a, oldObj.a); 
//undefined ,    ƒ say() {console.log('hi');}
console.log(newObj.b[0], oldObj.b[0]);
//null , undefined
console.log(newObj.c, oldObj.c);
// {} ,/ab+c/i
console.log(newObj.d.constructor, oldObj.d.constructor);
// ƒ Object() { [native code] }, ƒ person(pname) {this.name = pname;}

const oldObj = {};
oldObj.a = oldObj;
const newObj = JSON.parse(JSON.stringify(oldObj));
console.log(newObj.a, oldObj.a); // TypeError: Converting circular structure to JSON

1)对于正则表达式类型、函数类型等无法进行深拷贝(而且会直接丢失相应的值)。
2)它会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。
3).对象有循环引用,会报错
43,
this问题

  1. 全局作用域中的this指向window
  2. 函数体内的this 哪个对象调用这个函数,this指向谁
    call和apply改变函数内this的指向.png

    44,
    ajax请求过程
    1,创建XMLHttpRequest对象(异步调用对象)
    2,创建新的HTTP请求,指定方法,URL和验证信息
    3,发送HTTP请求
    4,异步处理请求的数据
    ajax.png

    45,
    url转换成json
    参数url--json.png

    46,
    js中的遍历
    object独有遍历方法
    1
    Object.keys.png

    2
    getOwnPropertyNames.png

    3
    Reflect.ownKeys.png

数组独有遍历方法


image.png

for..of.png

for...in遍历数组index,对象key

for...in.png

47,
ES6数组的扩展
1.复制、合并数组
image.png

2.rest参数必须在数组最后一项
image.png

3.类数组转为数组
from.png

4,
filter.png

  1. Array()存在不足,当参数为1个时候,参数为数组长度,当参数大于1时,参数为数组值


    Array.of.png
  2. Array.prototype.copyWithin(target, start = 0, end = this.length):
    target:复制到哪里去
    start:从哪里开始
    end:从哪里结束
    start和end若为负数,则是倒数 数组


    copyWithin.png
  3. find返回第一个符合条件的成员,若没有,返回undefind;
    findIndex:返回第一个符合条件的成员位置,若没有,返回-1;
    includes:返回true或者false,第二个参数为从哪里开始查找,若是负数,则倒数。


    find.png

    findIndex.png

    includes.png

    image.png

8.fill:填充数组

fill.png

9.flat 拉平数组
image.png

48,
js创建对象属性加引号和不加引号对区别
var info = {
'first-name':'ss',
name:'lh'
}
在使用非法命名规则的时候,必须加引号,其他情况两者都是可以的。还要注意的是:使用非法命名规则在获取属性的时候,不能用点语法(.first-name),必须使用中括号(info[first-name])。
49,
简洁的if-else判断写法
当case2和case3逻辑一样当时候,可以省去执行语句和break。

 // status 活动状态:1 开团进行中 2 开团失败 3 商品售完 4 开团成功
const onButtonClick = (status) => {
    switch (status) {
        case 1:
            sendLog('processing')
            jumpTo('IndexPage')
            break
        case 2:
        case 3:
            sendLog('fail')
            jumpTo('FailPage')
            break
        case 4:
            sendLog('success')
            jumpTo('SuccessPage')
            break
        default:
            sendLog('other')
            jumpTo('Index')
            break
    }
}

升级写法:

const actions = {
                        '1': ['processing', 'IndexPage'],
                        '2': ['fail', 'FailPage'],
                        '3': ['fail', 'FailPage'],
                        '4': ['success', 'SuccessPage'],
                        'default': ['other', 'Index']
                    }
                    const onButtonClick1 = (status) => {
                        let action  = actions[status] || actions['default'],
                        logName = action[0],
                        pageName = action[1];
                        sendLog(logName);
                        jumpTo(pageName);

                    }

Map对象: 打破了传统对象 键(字符串)--值对,而现在是值--值。

const actions = new Map([
                        [1, ['processing', 'IndexPage']],
                        [2, ['fail', 'FailPage']],
                        [3, ['fail', 'FailPage']],
                        [4, ['success', 'SuccessPage']],
                        ['default', ['other', 'Index']],
                    ])
                    const onButtonClick1 = (status) => {
                        let action  = actions.get(status) || actions.get('default');
                        sendLog(action[0]);
                        jumpTo(action[1]);

                    }

如果判断条件升级为两个,status 和 identity
最原始if--else判断方法:

/**
 * 按钮点击事件
 * @param {number} status 活动状态:1开团进行中 2开团失败 3 开团成功 4 商品售罄 5 有库存未开团
 * @param {string} identity 身份标识:guest客态 master主态
 */
const onButtonClick = (status, identity) => {
  if (identity == 'guest') {
    if (status == 1) {
      //do sth
    } else if (status == 2) {
      //do sth
    } else if (status == 3) {
      //do sth
    } else if (status == 4) {
      //do sth
    } else {
      //do sth
    }
  } else if (identity == 'master') {
    if (status == 1) {
      //do sth
    } else if (status == 2) {
      //do sth
    } else if (status == 3) {
      //do sth
    } else if (status == 4) {
      //do sth
    } else {
      //do sth
    }
  }
}

升级为Map后(把两个判断条件拼接成字符串):

const actions = new Map([
                        ['guest_1', () => {/*do sth...*/}],
                        ['guest_2', () => {/*do sth...*/}],
                        ['guest_3', () => {/*do sth...*/}],
                        ['guest_4', () => {/*do sth...*/}],
                        ['master_1', () => {/*do sth...*/}],
                        ['master_2', () => {/*do sth...*/}],
                        ['master_3', () => {/*do sth...*/}],
                        ['master_4', () => {/*do sth...*/}],
                        ['default', () => {/*do sth...*/}],
                    ]);
                    const onButtonClick1 = (identity, status) => {
                        let action  = actions.get(`${identity}_${status}`) || actions.get('default');
                        action.call(this)
                    }

再升级一下,去掉字符串拼接(Map可以是任意类型对数据作为key):

 const actions = new Map([
                        [{
                            identity: 'guest',
                            status: 1
                        }, () => {/* do sth... */}],
                        [{
                            identity: 'guest',
                            status: 2
                        }, () => {/* do sth... */}],
                        [{
                            identity: 'guest',
                            status: 3
                        }, () => {/* do sth... */}],
                    ])
                    const onButtonClick2 = (identity, status) => {
                        // 过滤出和参数相同的数组item
                        let action  = [...actions].filter(([key, value]) => (key.identity == identity && key.status == status));
                        action.forEach(([key, value]) => value.call(this));
                    }

如果1和2的处理逻辑一样呢(functionA),如下:

const actions = new Map([
                        [{
                            identity: 'guest',
                            status: 1
                        }, () => {/* functionA */}],
                        [{
                            identity: 'guest',
                            status: 2
                        }, () => {/* functionA */}],
                        [{
                            identity: 'guest',
                            status: 3
                        }, () => {/* functionB */}],
                    ])

可以把处理逻辑函数进行缓存:

const actions = () => {
                        const functionA = () => {/* do sth ... */}
                        const functionB = () => {/* do sth ... */}
                        return new Map([
                        [{
                            identity: 'guest',
                            status: 1
                        }, functionA],
                        [{
                            identity: 'guest',
                            status: 2
                        }, functionA],
                        [{
                            identity: 'guest',
                            status: 3
                        }, functionB],
                    ])
                    }
                    console.log([...actions()]);//[arr1, arr2, arr3]
                    const onButtonClick2 = (identity, status) => {
                        // 过滤出和参数相同的数组item
                        let action  = [...actions()].filter(([key, value]) => (key.identity == identity && key.status == status));
                        action.forEach(([key, value]) => value.call(this));
                    }

相同处理逻辑的函数写了好多遍,看着还是冗余,可以再次升级(正则表达式作为key):

const actions = () => {
                        const functionA = () => {/* do sth ... */}
                        const functionB = () => {/* do sth ... */}
                        return new Map([
                        [/^guest_[1-2]$/, functionA],
                        [/^guest_3$/, functionB],
                    ])
                    }
                    const onButtonClick2 = (identity, status) => {
                        // 过滤出和参数相同的数组item
                        let action  = [...actions()].filter(([key, value]) => (key.test(`${identity}_${status}`));
                        action.forEach(([key, value]) => value.call(this));
                    }

50,编写一个js函数,返回一个数组,数组由实现随机生成n个11-41之间的整数,且不重复。

function foo(n) {
            var arr = [];
            var isNum = !isNaN(Number(n));//判断n是不是一个数字,包含字符串类型的数字
            var isRandOk = (n >= 11 && n <= 41 && n <= 30) ? true : false;//判断n的取值是否符合要求
            if (n && isRandOk && isNum) {
                for (var i = 0; i < n; i++) {
                    var rand = Math.ceil(Math.random()*30+11);
                    if(arr.indexOf(rand) > -1){
                        i--
                    }else {
                        arr.push(rand)
                    }
                }
            }
            console.log(arr);
        }
        foo(11);

51,不使用循环,生成一个长度100的数组,且每一个元素等同于它的下标

var arr = [...Array(100).keys()];
console.log(arr);
var arr = Array.from({length:100}, (v,k) => k);
console.log(arr);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容

  • 转载说明 一、介绍 浏览器可以被认为是使用最广泛的软件,本文将介绍浏览器的工作原理,我们将看到,从你在地址栏输入g...
    17碎那年阅读 2,442评论 0 22
  • <a name='html'>HTML</a> Doctype作用?标准模式与兼容模式各有什么区别? (1)、<...
    clark124阅读 3,462评论 1 19
  • 医疗和家装作为目前鲜有的未被染指的行业一直顽强抵抗互联网春风的诱惑。医疗涉及人的健康安全以及国家管控,因此互联网程...
    Loren阅读 208评论 0 1
  • 最近,关于韩冬辉的妻子在公众号的发文红透朋友圈。文章主要讲述了一位勤恳工作的CTO与合伙人一起创业打拼,七年后被净...
    Demi001阅读 251评论 0 0