面试整理

时间:2019-09-18
本文章向大家介绍面试整理,主要包括面试整理使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

https://zhuanlan.zhihu.com/p/70659130

1.计算机基础知识
1.1计算机网络
https://www.cnblogs.com/theblogs/p/10438012.html

https://segmentfault.com/a/1190000017322866

缓存
https://my.oschina.net/leejun2005/blog/369148

http://caibaojian.com/http-cache.html

计算机网络了解吗?OSI七层模型?选择一个比较熟悉的层,介绍一下有哪些协议(字节跳动)

DNS的运行过程,DNS性能优化有哪些方法(字节跳动)https://blog.csdn.net/cat_foursi/article/details/71194397

https协议加密具体过程(字节跳动)https://blog.csdn.net/qq_32998153/article/details/80022489 https://blog.csdn.net/wangjun5159/article/details/51510594

https://www.cnblogs.com/mibloom/p/9635913.html

https和http区别,对称加密和非对称加密区别(字节跳动)

http1.0和http1.1和http2.0(字节跳动)

跨域有哪些方法(蘑菇街)

TCP三次握手,为什么是三次(作业帮)

http请求包括什么,http应答包括什么(作业帮)https://www.jianshu.com/p/2e00a452f874

了解哪些状态码(作业帮)

输入url到页面出现发生了什么(作业帮)

浏览器渲染机制(作业帮)https://segmentfault.com/a/1190000014018604

什么是同源策略(如何判断是否同源),CORS策略(作业帮)

CSRF和XSS是什么,如何预防(作业帮)https://www.jianshu.com/p/c2f326a4972e

localStorage和sessionStorage区别,localStorage最大存储量(美团)

CORS机制(美团)

TCP三次握手,为什么不是四次,为什么不是两次(美团)

浏览器渲染机制,js阻塞加载(美团)

CORS原理(阿里)https://www.jianshu.com/p/af02bc9c1b2b

网络安全了解哪些?如何预防sql注入,XSS,CSRF(阿里)https://blog.csdn.net/qq_42655663/article/details/96185529

iso七层模型,每一层模型的经典协议(阿里)

http1.0和http1.1和http2.0的区别(阿里)

HTTP状态码有哪些(酷家乐)

cookie,localStorage,sessionStorage的区别(酷家乐)

HTTP持续连接实现原理(酷狗)https://blog.csdn.net/neninee/article/details/79634187

以下摘自图解HTTP:

持久连接(HTTP Persistent Connections,也称为HTTP keep-alive或HTTP connection reuse)

持久连接的特点:只要任意一端没有明确提出断开连接,则保持TCP连接状态。

旨在建立一次TCP连接后进行多次请求和响应的交互。

持久连接的好处在于减轻了服务器端的负载连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。另外,减少开销的那部分时间,使这样Web页面的显示速度也就相应提高了。

在HTTP/ 1.1中,所有的连接默认都是持久连接,但在HTTP/ 1.0内并未标准化。虽然有一部分服务器通过非标准的手段实现了持久连接,但服务器端不一定能够支持持久连接。毫无疑问,除了服务器端,客户端也需要支持持久连接。

http协议是什么,请求和响应的构成,如何区分一个请求的头部和实体(中间有一个空行)(猫眼)

http有哪些方法,为什么要有这些方法(语义化)(猫眼)https://www.cnblogs.com/yinrw/p/10694474.html

状态码3开头的有哪些,浏览器收到301和302怎么做,304用在哪些场景(猫眼)

cookie相关,cookie用在什么场景,cookie有哪些性质(猫眼)

cookie和session的区别(我说了我的项目中用了sessionStorage)(猫眼)

简历中写了了解web安全所以问我对XSS和CSRF哪个比较熟悉,我对CSRF中的cookie不太熟悉所以说的XSS然后就问我XSS攻击方式防御手段,H5中哪些标签会被XSS利用,如何处理要展示js代码的部分(例如csdn中的md编辑器)(猫眼)

恩,你提到了SSL层加密哈,具体说一下是怎么加密的?(猫眼)https://blog.csdn.net/u014201191/article/details/81977965

那你说说常见的状态码吧(我:200,304, 400 ,500一大堆balabala) 什么时候返回304呢? (猫眼)

你平时都是怎么清除这种本地的缓存呢?(我:ctrl + f5。。。我真是这么说的。。。可能是我当时就没理解啥意思)(猫眼)

HTTP缓存具体说一下(我:强缓存,协商缓存 balabala)(猫眼)

你提到了cache-control优先级比较高吧,那你说说如果我现在有cache-control还有Etag,还会从服务器判断是否命中协商缓存吗?(我:我觉得不会吧,毕竟cache-control优先级高,直接就拿本地缓存然后返回200就完事了,然后小姐姐表示赞同。。。emmmm。。。)(猫眼)https://www.jianshu.com/p/fd00f0d02f5f

cookie有了解过吗?(我:了解过,然后说了一下cookie) 知道cookie一般用来存什么嘛?知道cookie的http-only字段吗?(我说禁止浏览器操作cookie,在XSS里面应该是这么用的)然后小姐姐说:呦,还知道XSS呢。emmmm。。。。(猫眼)

HTTP分层知道吗?(我:不知道,这个真不会)(猫眼)

然后在石墨文档写了个代码,让***作js的cookie。。。emmm。。。我不会。。。真的,然后小姐姐问我,你没在js写过吧,我说对,然后小姐姐说你应该是在node里面直接用的,我说是的。。。(猫眼)

http状态码有很多,说一下304(蚂蚁金服)

浏览器是怎么判断命中缓存的(蚂蚁金服)https://blog.csdn.net/u010472499/article/details/54290505

服务端怎么判断(蚂蚁金服)

判断request header的哪个字段(蚂蚁金服)

强缓存和协商缓存的区别 (腾讯)https://www.jianshu.com/p/1a1536ab01f1

304状态码 (腾讯)

域名解析方式 (腾讯)

解释一下HTTPS的过程,能够防止怎样的攻击,密钥是什么,证书是什么 https://baike.baidu.com/item/%E5%AF%86%E9%92%A5/101144?fr=aladdin

https://baike.baidu.com/item/%E5%AF%86%E9%92%A5%E8%AF%81%E4%B9%A6/5816730?fr=aladdin

HTTPS可以预防DNS劫持以外,还起到数据加密协议传输等。

1.2数据结构
如何判断一个链表是否有环(独到科技)https://blog.csdn.net/Leon_cx/article/details/81430822

一个二叉树中找到两个节点的最小公共父节点(独到科技)

计算机存储中的堆和栈的区别(酷家乐)

数据结构数组和链表的区别(酷家乐)

快排的原理,为什么比冒泡排序快(酷狗)

归并排序的原理(猫眼)

写代码:写一下归并排序合并两个有序数组的过程(猫眼)

写代码:求多个数组的交集(用归并的思想进行优化)(猫眼)https://blog.csdn.net/DoWhatIWant_comeon/article/details/70306766

写代码:递归实现1000!(尾递归调用优化)(猫眼)

栈和链表的联系和区别,写代码:用链表实现栈(猫眼)https://blog.csdn.net/qq_33054265/article/details/82433047

封装一个方法实现栈不能用数组(提示:可以用链表的数据结构通过指针来倒序输出)(猫眼)

数据结构怎么样?(我就知道,计算机网络完了就是数据结构,奈何本人数据结构是真菜,然后我就说了我就学了栈、队列、链表)(猫眼)

那你说说这些数据结构的概念(我:balabala)单链表是啥?(贼感动,小姐姐知道我数据结构不好,就没难为我)(猫眼)

知道哪些排序?(我:冒泡,快排,归并)分别说一下这几种排序。balabala(猫眼)

快排复杂度 (腾讯)

从32G的文件中找出出现频率最高的10个IP地址(提示我归并排序,然而我还是不会啊。。。) (腾讯)https://blog.csdn.net/fycy2010/article/details/46945641

称硬币:有8个硬币,其中有一个假币轻一点,怎么找出这个假币 不告诉你假币轻重,怎么找 (腾讯)

70%的人喜欢足球,80%的人喜欢篮球,90%喜欢排球,同时喜欢足球和篮球的人有多少 (腾讯)

递归式说一下 (腾讯)

快排时间复杂度,为什么会出现最差情况,怎么解决 (腾讯)https://blog.csdn.net/gettogetto/article/details/58200149

问了一下像 Excel 这样的表格应该用什么数据结构存储(面试官最后解释了一下应该是一个索引树,比如B+树)(阿里)

写写代码,邮件发了一个在线编辑器的链接(阿里)

根据JS数组的map函数写一个二叉树的map函数

写一个n叉树的map函数

1.3操作系统
进程线程是什么,进程间的通信有哪些方法(字节跳动)

进程和线程的区别:
https://blog.csdn.net/u013693367/article/details/81092880

https://www.cnblogs.com/wangzhenghua/p/4447570.html

进程间的通信有哪些
https://www.cnblogs.com/zgq0/p/8780893.html

1.4数据库
数据库第一范式,第二范式,第三范式(字节跳动)

2.html
html语义化
http://www.daqianduan.com/6549.html

3.css
给一个淘宝的页面,写一下大概如何布局(字节跳动)

CSS盒模型(box-sizing属性)(字节跳动)

em和rem的区别(蘑菇街)

CSS雪碧图是什么(蘑菇街)

重绘和重排,哪些属性会触发重绘,哪些属性会触发重排(蘑菇街)

CSS实现三角形,箭头(作业帮)

CSS垂直居中的方法(作业帮)

CSS3新特性了解哪些(京东)

CSS的flex布局(独到科技)

如何实现一个下划线(和text-decoration里的underline不一样),答案:用box-shadow(独到科技)

w3c标准盒子模型和IE模型有什么区别(阿里)

CSS的display有哪些取值(阿里)

flex布局用在哪些场景下(阿里)

如何适配不同的屏幕(阿里)

如何实现水平垂直居中(元素定长和不定长)(酷家乐)

position有哪些属性,有什么区别,除了定位上的不同还有什么区别(酷家乐)

CSS选择器优先级(酷狗)

三列布局的实现方式列出几种来,我就说出三种flex float inline-block(猫眼)

flex 中的 jusitify-content是什么意思(猫眼)

CSS的水平垂直居中?已知宽高和未知宽高的都说一下?(猫眼)

box-sizing的两个属性(蚂蚁金服)

background-origin是干嘛的(蚂蚁金服)

background-origin:30% 30%是什么意思(蚂蚁金服)

4.js
闭包
https://www.jianshu.com/p/865f40d916a6

https://www.jb51.net/article/114535.htm

https://www.cnblogs.com/wx1993/p/7717717.html

数组
声明数组

使用数组

数组长度

遍历数组

数组属性

constructor 返回创建数组对象的原型函数

length 设置或返回数组元素的个数

prototype 允许你向数组对象添加属性或方法

数组常用方法

添加数组

push 从后面推进去,返回数组长度

unshift 从前面放入,返回数组长度

删除数组内容

pop 删除最后一个,返回最后一个值

shift 删除第一个,返回第一个

连接两个数组

concat 用于连接两个或多个数组,它不会改变现有的数组,而仅仅会返回被连接数组的一个副本

把数组转为字符串

join 将数组各个元素通过指定的分隔符进行连接成为一个字符串

把字符串转为数组

split 把一个字符串分割成字符串数组

其他

正则
es通过RegExp类型来支持正则表达式。使用类似Perl的语法,就可以创建一个正则表达式

var expression = / pattern / flags;
pattern部分可以是任何简单或复杂的正则表达式,可以包含字符类,限定符,分组,向前查找以及反向查找;

每个正则表达式都科带有一或多个标志(flags),用以标明正则表达式的行为。正则表达式的匹配模式支持下列3个标志。

g: 表示全局(global)模式,及模式将被应用于所有字符串,而不是在发现第一个匹配项时立即停止。

i: 表示不区分大小写(case-insensitive)模式,就是在确定匹配项时忽略模式与字符串的大小写;

m : 表示多行(multiline)模式,即在到达这一行文本末尾时还会继续查找下一行是否存在与模式匹配的项。

与大多数语言中的正则表达式类似,模式中使用的所有元字符都必须转义。正则表达式中的元字符包括

([{^$|?*+-.}])
这些元字符在正则表达式中都有一种或多种用途,因此想要匹配字符串中包含的这些字符,就必须对它们进行转义。

//匹配第一个'bat'或者'cat',不区分大小写
var pattern1 = /[bc]at/i;
//匹配第一个[bc]at,不区分大小写
var pattern2 = /[bc]at/i;
//匹配所有以'at'结尾的3个字符的组合,不区分大小写
var pattern3 = /.at/gi;
//匹配所有以'at',不区分大小写
var pattern4 = /.at/gi;
前面举的这些例子都是以字面量形式来定义的正则表达式。另一种创建正则表达式的方式是使用RegExp构造函数,它接收两个参数:一个是要匹配的字符串模式,一个是可选的标志字符串。可以使用字面量定义的任何表达式,都可以使用构造函数来定义,如下面的例子所示。

var pattern1 = /[bc]at/i;
var pattern2 = new RegExp("[bc]at","i");
pattern1和pattern2是完全等价的正则表达式。

注意:传递给RegExp函数的两个参数都是字符串(不能把正则表达式字面量传给RegExp构造函数)。由于RegExp构造函数的两个参数都是字符串,所以在某些情况下要对字符进行双重转义。所有元字符都必须双重转义,那些已经转义过的字符也是如此,例如\n(字符\在字符串中通常被转义为 \ ,而在正则表达式字符串中就会变成 \\ ).

正则实例属性
RegExp的每个实例都具有下列属性,这些属性可以取得有关模式的各种信息。

global :布尔值,表示是否设置了g标志。

ignoreCase : 布尔值,表示是否设置了i标志

lastIndex :整数,表示开始搜索下一个匹配项的字符位置,从0 算起。

multiline: 布尔值,表示是否设置了m标志。

source : 正则表达式的字符串表示,按照字面量形式而非传入构造函数中的字符串模式返回。

    var pattern1 = /\[bc\]at/i;
    
    alert(pattern1.global);     //false
    alert(pattern1.ignoreCase); //true
    alert(pattern1.multiline);  //false
    alert(pattern1.lastIndex);  //0
    alert(pattern1.source);     //"\[bc\]at"


var pattern2 = new RegExp("\[bc\]at", "i");

    alert(pattern2.global);     //false
    alert(pattern2.ignoreCase); //true
    alert(pattern2.multiline);  //false
    alert(pattern2.lastIndex);  //0
    alert(pattern2.source);     //"\[bc\]at"


正则实例方法
exec()

专门为捕获组而设计的。接收一个参数,即要应用模式的字符串,然后返回包含第一个匹配项信息的数组;或者在没有匹配项的情况下返回null。返回的数组是Array的实例,但包含两个额外的属性:index和input。其中,index表示匹配项在字符串中的位置,而input表示应用正则表达式的字符串。

在数组中,第一项是与整个模式匹配的字符串,其他项是与模式中的捕获组匹配的字符串(如果模式中没有捕获组,则该数组只包含一项)

    var text = "mom and dad and baby";
    
    var pattern = /mom( and dad( and baby)?)?/gi;
    var matches = pattern.exec(text);
    
    alert(matches.index);    //0
    alert(matches.input);    //"mom and dad and baby"
    alert(matches[0]);       //"mom and dad and baby"
    alert(matches[1]);       //" and dad and baby"
    alert(matches[2]);       //" and baby"

对于exec()方法而言,即使在模式中设置了全局标志(g),它每次也只会返回一个匹配项。

在不设置全局标志的情况下,在同一个字符串上多次调用exec()将始终返回第一个匹配性的信息。

而在设置全局标志的情况下,每次调用exec()则都会在字符串中继续查找新匹配项。

    var text = "cat, bat, sat, fat";        
    var pattern1 = /.at/;
    
    var matches = pattern1.exec(text);        
    alert(matches.index);    //0
    alert(matches[0]);       //"cat"
    alert(pattern1.lastIndex);//0


matches = pattern1.exec(text);
alert(matches.index); //0
alert(matches[0]); //"cat"
alert(pattern1.lastIndex);//0

var pattern2 = /.at/g;

    var matches = pattern2.exec(text);        
    alert(matches.index);    //0
    alert(matches[0]);       //"cat"
    alert(pattern2.lastIndex);//0


matches = pattern2.exec(text);
alert(matches.index); //5
alert(matches[0]); //"bat"
alert(pattern2.lastIndex);//0
test()

接受一个字符串参数。在模式与该参数匹配的情况下返回true;否则,返回false。在只想知道目标字符串与某个模式是否匹配,但不需要知道其文本内容的情况下,使用这个方法非常方便。因此,test()经常被用于if语句中。

var text = "000-00-0000";
var pattern = /\d{3}-\d{2}-\d{4}/;

if(pettern.test(text)){
alert("The pattern was matched.");
}
在这个例子中,我们使用正则表达式来测试了一个数字系列。如果输入法人文本与模式匹配,则显示一条信息。这种用法经常出现在验证用户输入的情况下,因为我们只想知道输入是不是有效,至于它为什么无效就无关紧要了。

toLocalString()和tostring()方法都会返回正则表达式的字面量,与创建正则表达式的方式无关。

    var pattern = new RegExp("\\[bc\\]at", "gi");
    alert(pattern.toString());    // /\[bc\]at/gi
    alert(pattern.toLocaleString());    // /\[bc\]at/gi

正则构造函数属性
RegExp构造函数包含一些属性(这些属性在其他语言被看成是静态属性)。这些属性适用于作用域中的所有正则表达式,就是可以通过两种方式访问它们。换句话说,这些属性分别有一个长属性名和一个短属性名(Opera例外,它不支持短属性名)。

1566529180439

使用这些属性可以从exec()或test()执行的操作中提取出更具体的信息。

    var text = "this has been a short summer";
    var pattern = /(.)hort/g;
    
    /*
     * Note: Opera doesn't support input, lastMatch, lastParen, or multiline.
     * Internet Explorer doesn't support multiline.
     */        
    if (pattern.test(text)){
        alert(RegExp.input);               //this has been a short summer
        alert(RegExp.leftContext);         //this has been a            
        alert(RegExp.rightContext);        // summer
        alert(RegExp.lastMatch);           //short
        alert(RegExp.lastParen);           //s
        alert(RegExp.multiline);           //false
    }

例子使用的长属性名都可以用响应的短属性名来代替。只不过,由于这些短属性名大都不是有效的es标志符,因此必须通过方括号语法来访问它们。

    var text = "this has been a short summer";
    var pattern = /(.)hort/g;
    
    /*
     * Note: Opera doesn't support short property names.
     * Internet Explorer doesn't support multiline.
     */        
    if (pattern.test(text)){
        alert(RegExp.$_);               //this has been a short summer
        alert(RegExp["$`"]);            //this has been a            
        alert(RegExp["$'"]);            // summer
        alert(RegExp["$&"]);            //short
        alert(RegExp["$+"]);            //s
        alert(RegExp["$*"]);            //false
    }

除了上面介绍的几个属性之外,还有多达九个用于存储捕获组的构造函数属性。访问这些属性的语法 RegExp.$1、RegExp.$2....RegExp.$9,分贝用于存储第一,第二.....第九个匹配的捕获组。在调用exec()或者test()方法时,这些属性会被自动填充。

    var text = "this has been a short summer";
    var pattern = /(..)or(.)/g;
          
    if (pattern.test(text)){
        alert(RegExp.$1);       //sh
        alert(RegExp.$2);       //t
    }

这里创建了一个包含两个捕获组的模式,并用该模式测试了一个字符串。即使test()方法只返回了一个布尔值,但RegExp构造函数的属性$1和$2也会被匹配相应捕获组的字符串自动填充。

高级函数技巧
函数柯里化
用于创建已经设置了一个或多个参数的函数。函数柯里化的基本方法是函数绑定是一样的:使用一个闭包返回一个函数。两者的区别在于,当函数被调用时,返回的函数还需要设置一些传入的参数。

function add(num1,num2){
return num1+num2;
}
function curriedAdd(num2){
return add(5,num2);
}
alert(add(2,3));//5
alert(curriedAdd(3));//8
上面定义了两个函数:add()和curriedAdd()。后者本质上是在任何情况下第一个参数为5的add()版本。尽管从技术上来说curriedAdd()不是函数柯里化的函数和必要参数。

柯里化函数的通用方式:
function curry(fn){
var args = Array.prototype.slice.call(arguments, 1);
return function(){
var innerArgs = Array.prototype.slice.call(arguments),
finalArgs = args.concat(innerArgs);
return fn.apply(null, finalArgs);
};
}

    function add(num1, num2){
        return num1 + num2;
    }
    
    var curriedAdd = curry(add, 5);
    alert(curriedAdd(3));   //8

    var curriedAdd2 = curry(add, 5, 12);
    alert(curriedAdd2());   //17

curry函数的主要工作就是将被返回函数的参数进行排序。curry()的第一个参数是要进行柯里化的函数,其他参数是要传入的值。为了获取第一个参数之后的所有参数,在arguments对象上调用了slice()方法,并传入参数1表示被返回的数组包含从第二个参数开始的所有参数。然后args数组包含了来自外部函数的参数。在内部函数中,创建了innerArgs数组用来存放所有传入的参数(又一次用到了slice())。有了存放外部函数和内部函数的参数数组后,就使用concat()方法将他们组合为finalArgs,然后使用apply()将结果传递给该函数。注意:这个函数并没有考虑到执行环境,所以调用apply()时第一个参数时null。

题目
垃圾回收机制(字节跳动)

https://www.cnblogs.com/sunhuahuaa/p/7655587.html

写代码,DOM操作将所有页面元素存为一个{key:count}的结构,即统计在页面中每种元素的数量,将元素根据count进行排序。(字节跳动)

写代码:多维数组展为一维数组(如:[[1,2],3,[4,5,6],[7,8]]->[1,2,3,4,5,6,7,8])(字节跳动)https://blog.csdn.net/qq_25842063/article/details/82385488 https://segmentfault.com/a/1190000010287443

写代码:自己实现一个instanceof(字节跳动) https://www.jianshu.com/p/99d0004bae4e

对于原型链的理解,new的过程中发生了什么,写代码:自己实现一个new(字节跳动) https://www.jianshu.com/p/9bf81eea03b2

map,forEach的区别(蘑菇街) https://segmentfault.com/a/1190000013368741?utm_source=channel-hottest

写代码:多维数组展开成一维数组,分析算法的时间复杂度,用es6的什么方法可以实现(flat)

写代码:数组去重有哪些方法(作业帮)https://segmentfault.com/a/1190000016418021?utm_source=tag-newest

写代码:用闭包实现add()函数,第n次调用的时候输出n(作业帮)https://blog.csdn.net/zhq2005095/article/details/56515012

this的指向问题:
var a=2; var obj={ a:1, b:this.a, fun:function(){ console.log(this.b); } }
输出结果为2,分析原因(作业帮)

写代码:实现call函数(作业帮)https://www.jianshu.com/p/af3f41d8ef99

js动态加载,eval()方法(美团)https://www.jb51.net/article/17992.htm https://www.jb51.net/article/85804.htm

写代码:请求一个require.js文件,并统计文件中'require'的数量,分析时间复杂度,如何优化(美团)

如何实现一个轮播图效果(京东)

js数组的方法(独到科技)

js对象的方法(独到科技)https://blog.csdn.net/moakun/article/details/81807885

js闭包(独到科技)

Json是什么,为什么要有Json(独到科技)

ajax原生操作的步骤(独到科技) https://blog.csdn.net/c__dreamer/article/details/80456565

数组排序的方法有哪些,简述归并排序(独到科技)

如何实现一个数组的深拷贝(独到科技)https://segmentfault.com/a/1190000010150234

从后端返回一个很大的数组,如何实现分页显示(通过数组下标进行对应)(独到科技)

js闭包是什么,什么是内存泄漏,如何解决内存泄漏问题(阿里) https://blog.csdn.net/weixin_34341117/article/details/93722631

js垃圾回收机制(阿里)

js基本数据类型(包括es6新增的Symbol)(阿里)

原生ajax原理,ajax和fetch的区别,fetch支持http的哪些方法(阿里) https://blog.csdn.net/c__dreamer/article/details/80456565

option方法可以发送那些内容(阿里) 上一题中的option参数

数组的reduce方法(阿里)

s中找到一个数组最大值的方法,分析复杂度(阿里)

es6的let,const和var区别,const绑定的对象能不能修改属性值(酷家乐)

event-loop原理,宏任务,微任务有哪些(酷家乐)

es5实现继承(酷狗)https://www.cnblogs.com/annika/p/9073572.html

闭包的应用场景(酷狗)

es5中的模块化,CommonJS等(酷狗)

setTimeout和Promise的区别,如何实现Promise(酷狗)

jQ选择器的实现原理(酷狗)

实现柯里化,foo(1)(2)(3)(4)(猫眼)https://segmentfault.com/a/1190000012364000

实现一个function A,使得
a1=new A(); a2=new A(); console.log(a1.value);//1 console.log(a2.value);//2
即每new一次value加1(猫眼)

写代码:实现乒乓球计分,给一个数组,[1,-1,1,1….],1代表A赢,-1代表B赢,先赢11分且得分高过对方两分以上获胜,计算最后的比分:如大比分1:0,小比分10:5(猫眼)

封装一个函数能够把url中的query部分转化成query对象,注意审题我这里就没仔细看题整体不难注意用正则或者str.replace替换字符串达到题目要求

为什么构造函数的方法要放在prototype里边为什么不直接用this.的方式声明,因为prototype占用一个存储空间实例通过proto指针指向prototype,可以减少内存占用减少不必要的开销

一个代码题,要实现秒杀倒计时的功能,一开始给我一段错误代码,(vue的代码)用的computed属性主要考对计算属性是否熟练,要知道计算属性监控的是哪一部分的属性,之后让我改正。这个还是比较简单的。根据这个代码题又延伸出为什么两个计时器会同时计时,先问的js是如何做到异步的,js的多线程是怎么实现的,然后才问的计时器的原理,因为js是单线程所以要通过浏览器其他线程的辅助,比如ui线程、事件线程、计时器线程等等,然后问的计时器线程应该也是单线程如何让两个计时器同时开始计时的。

然后有考的一个代码题for循环里每次绑定一个点击事件最后问输出这个和for循环里放一个定时器是一个原理都是最后输出len(长度)比较简单就不多说了。(猫眼)

之后有封装一个node的Emiter就是on和emit方法,因为我说我看过js设计模式所以问得我这个观察者模式(猫眼)

因为我看了js高性能问得我性能方面如何优化。(猫眼)

在学前端的过程中遇到的比较难的问题(已解决的),我说的async await的原理因为我在看《你不知道的JavaScript》的时候看到promise和generator发现两者结合合asnyc和await很像然后研究源码的时候遇到的问题。(猫眼)

然后写了一个代码题:数组拍平 解释一下Array.isArray()(猫眼) https://www.cnblogs.com/guan-shan/p/10165737.html

还知道哪些数组的方法(猫眼)

说一下JS的原型链吧?能干嘛?(猫眼)

那就手写一个继承吧!(猫眼)

ES6会的挺多的哈,知道Promise(猫眼)

Promise的then方法第一个函数参数的参数是干啥的?(我感觉小姐姐问这个是因为我没提到Promise的三个状态,然后我就说了一遍Promise的三个状态,说了一下resolve的传参,说了catch捕获错误之类的。。。老规矩:balabala)(猫眼)

JS怎么获取一个写好的盒子的宽度(猫眼)

数组的遍历方法有很多,说几个(蚂蚁金服)

map和forEach的区别(蚂蚁金服)

在循环过程中可以跳出循环吗(蚂蚁金服)

有哪些类似数组的结构(蚂蚁金服)

说一下set(蚂蚁金服)

说一下map和weekmap的区别(蚂蚁金服)

跨域的方式(蚂蚁金服)

jsonp的原理(蚂蚁金服)

像下拉加载这种功能你是怎么实现的 (蚂蚁金服,以下一系列问题)

说 一下事件委托 还了解哪些语言

数据库有用过哪些

数据库索引了解过吗

它的查询方式是什么样的

范式这些知道吗

mysql和mongodb你是怎么选的

那个聊天是存储是怎么实现的

mysql每一行这样存储不是也行吗

除了慕课网还有看过哪些网站吗

算法知道哪些

现在前端其实要注重用户体验

你这样需要点击是不是用户体验不太好

弹窗的几种形式

有看过哪些UI设计的网站吗

如果让你设计一个按钮要有几种状态

你觉得你的优势是什么

为什么会去学three.js

three.js底层是什么知道吗

webgl原理了解吗

矩阵变换知道吗

先进行translate再rotate和先rotate再translate有什么区别

实现类似百度输入框提示--手撕代码 (腾讯) https://www.jb51.net/article/75781.htm

要求点击可以补全输入--手撕代码 (腾讯) https://sky-yibai.iteye.com/blog/1814001

手撕代码(QQ远程):大数加法 (腾讯) https://www.jianshu.com/p/c51d63028371 https://www.jb51.net/article/48749.htm

正则表达式匹配QQ号 (腾讯)

宏任务和微任务 (腾讯)

js事件循环机制 (腾讯)

7:45时针和分针的角度 (腾讯)

统计文章中出现次数最多的单词 (腾讯) https://www.jb51.net/article/108905.htm

debounce了解吗(啥,,哦哦,,防抖,解释一下,然后手写了一下代码)https://zhuanlan.zhihu.com/p/73723200 (阿里)

然后通过这段代码引申出了一些别的问题

let和var和const,回答的时候提到了块级作用域

箭头函数,箭头函数和普通函数的区别(语法和this指向)

...args是什么(我顺便回答了和arguments的区别)

闭包

为什么timer声明的时候没有初始化为0或者null(undefined会在if时类型转化成false,然后解释了可以转化成false的各种情况)

call和apply的区别
本来想让我再写一个throttle(节流函数,平时确实没有关注过英文名hiahiahia)

介绍一下vue(提到了mvvm)

vue的原理(数据劫持,发布订阅模式/监听者模式)

说说什么是闭包吧(阿里)

有用过其他框架或者类库吗(jQuery)(阿里)

jQuery是什么,这个$是什么(阿里)

你什么时候用jQuery什么时候用vue(阿里)

我看到你博客中有写到前端的性能优化,介绍一下(我从两方面回答的,网络性能上的优化和本地渲染过程中的优化,然后突然被打断)(阿里)

你提到http2可以不用刻意减少请求,介绍一下http2(阿里)

手写代码:输入一个数字n,输出从1到n的所有排列,比如输入3,输出123、132、213、231、312、321https://www.jb51.net/article/39291.htm

如何控制字节的缺点呢(emmm,,对不起对不起)(阿里)

4.1基本概念

语法

关键字和保留字

变量

数据类型

操作符

语句

函数

小结

4.1.1 语法
区分大小写

es中的一切(变量,函数名和操作符)都区分大小写。

标识符

注释

严格模式

严格模式为js定义了一种完全不同的解析与执行环境,在严格环境下,es3中一些不确定的行为将得到处理,而且对某些不安全的操作会抛出错误。要在脚本中启用严格模式,可以在顶部添加如下代码:

use strict

语句

es中的语句以一个分号结尾;如果省略分号,则由解析器确定语句的结尾;虽然语句结尾的分号不是必须的,但我们建议任何时候都不要省略他。

4.1.2 关键字和保留字
4.1.3 变量
es的变量是松散类型的,所谓松散类型就是可以用来保存任何类型的数据。换句话说,每个变量仅仅是一个用于保存值得占位符而已。定义变量时使用var操作符,后跟变量名。如下所示:

var message;
这段代码定义了一个名为message的变量,该变量可以用来保存任何值(像这样未经初始化的变量,会保存一个特殊的值---undefined)。es也支持直接初始化变量,因此在定义变量的同时可以设置变量的值:

var message = "hi";
变量message中保存了一个字符串值“hi”。像这样初始化变量并不会把他标记为字符串类型。初始化的过程就是给变量赋一个值那么简单。因此,可以在修改变量值的同时修改值得类型。

var message = "hi";
message = 100;//有效,但是不推荐
不建议修改变量所保存值得类型,但是这种操作在es中完全有效。

注意:使用var操作符定义的变量会成为定义该变量的作用于中的局部变量。也就是说,如果在函数中使用var定义一个白那辆,那么这个变量在函数退出后就会被销毁。例如:

function test(){
var message = "hi";//局部变量
}
test();
alert(message);//错误
变量message是在函数中使用var定义的。当函数被调用时,就会创建该变量并为其赋值。而在此之后,这个变量又会立即被销毁,因此例子中的下一行代码就会报错。不过,可以像下面这样圣罗var操作符,从而创建一个全局变量:


function test(){
message = "hi";//局部变量
}
test();
alert(message);//"hi"
这个例子省略了var操作符,因而message就成了全局变量。这样,只要调用过一次 test()函数,这个变量就有了电仪,就可以在函数外部的任何地方被访问到。

注意:虽然省略var操作符可以定义全局变量,但这也不是我们推荐的做法。因为在全局作用域中定义的全局变量很难维护,而且如果有意的忽略了var操作符,也会由于相应变量不会马上就有定义而导致不必要的混乱。

4.1.4数据类型
有五种简单数据类型:Undefined,Null,Boolean,Number和String

还有一种复杂数据结构:Object,Object本质上是由一组无序的名值对组成的。

typeof操作符
检测给定变量的数据类型。

var message = "some string";
alert(typeof message); //"string"
alert(typeof 95); //"number"
typeof操作符法的操作数可以是变量,也可以是数值字面量。注意,typeof是一个操作符而不是一个函数,因此例子中的圆括号尽管可以使用,但不是必需的。

typeof操作符会返回一些令人迷惑但技术上却正确的值。比如,调用 typeof null 会返回“Object”,因为特殊值null被认为是一个空的对象引用。

Undefined
在使用var声明变量但未对其加以初始化时,这个变量的值就是undefined,例如

    var message;
    alert(message == undefined);    //true

包含undefined值得变量与尚未定义的变量还是不一样的,例如

   var message;     //this variable is declared but has a value of undefined
    
    //make sure this variable isn't declared
    //var age
    
    alert(message);  //"undefined"
    alert(age);      //causes an error

对于尚未声明的变量只能执行一项操作,即使用typeof操作符检测其数据类型。

令人困惑的是:对未初始化的变量执行typeof操作符会返回undefined值,而对未声明的变量执行typeof操作符同样也会返回undefined值。

    var message;     //this variable is declared but has a value of undefined
    
    //make sure this variable isn't declared
    //var age
    
    alert(typeof message);  //"undefined"
    alert(typeof age);      //"undefined"

Null类型
从逻辑角度看,null值表示一个空对象指针,而这也是使用typeof操作符检测null时会返回object的原因,如下所示

    var car = null;
    alert(typeof car);   //"object"

如果定义的变量准备在将来用于保存对象,那么最好将该变量初始化为null而不是其他值。这样一来,只要直接检查null值就可以知道相应的变量是否已经保存了一个对象的引用。

Number类型
String类型
Object类型
es中的对象其实就是一组数据和功能的集合。对象可以通过执行new操作符后跟要创建的对象类型的名称来创建。

var o = new Object();
在es中,如果不给构造函数传递参数,则可以省略后面的那一对圆括号。但是不推荐。

var o = new Object;
Object的每个实例都具有下列属性和方法:

constructor:保存着用于创建当前对象的函数

hasOwnProperty(propertyName):用于检查给定的属性在当前实例中(而不是在实例的属性中)是否存在。

作为参数的属性名必须与字符串形式指定

isProperty(object):用于检查传入的对象是否是另一个对象的原型。

propertyIsEnumerable(propertyName):用于检查给定的属性是否能够使用for-in 语句来枚举。和hasOwnProperty一样,作为参数的属性名必须与字符串形式指定

toLacalString():返回对象的字符串表示,该字符串与执行环境的地区对应。

toString():返回对象的字符串表示

valueOf():返回对象的字符串,数值或布尔值表示。通常与toString()方法的返回值相同。

4.1.5 操作符
加法操作符
如果有一个操作符是字符串,就要应用一下规则:

如果两个操作符都是字符串,则将第二个操作数与第一个操作数拼接起来;

如果只有一个操作数是字符串,则将另一个操作符转换为字符串,然后再将两个字符串拼接起来。

4.1.7函数
4.2 变量,作用域和内存问题
4.2.1 基本类型和引用类型的值
基本类型:undefined,null,boolean,number和string(按值访问,因为可以访问保存在变量中的实际的值)

引用类型:指的是那些可能由多个值构成的对象(引用类型的值是保存在内存中的对象)。

与其他语言不同,js不允许直接访问内存中的位置,也就是说不能直接惭怍对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。因此,引用类型的值是按引用访问的。

复制变量值:
从一个变量向另一个变量复制时, 如果基础类型, 创建一个新值, 然后把值 复制到新变量上,两个变量互相没有影响

var num1 = 5;
var num2 = num1;
1565507875065

但是,如果时引用类型, 复制的是 引用这个对象的指针, 所以两个变量会相互影响.

  var obj = new Object();
  obj.name = '我是obj1';
  var obj2 = obj;
  obj2.name = '我是obj2';
  console.log(obj.name); // 我是obj2

1565507980331

传递参数:
有函数的参数都是按值传递的,基础类型会复制值给参数, 而引用类型 会把指针复制给参数,所以把对象传入函数中外部对象依然会改变.

类型检测:
typeof 用来检测基础类型, instanceof 用来检测引用类型,如果instanceof 检测了基础类型 就会返回false

instanceof ----如果给定的是引用类型,根据它的原型链识别

4.2.2 执行环境和作用域
执行环境
决定了变量或函数有权访问的其他数据, 每个执行环境 都有一个与之关联的变量对象, 对象中存放着环境定义的所有变量与函数, 每一个函数都有自己的执行环境, 当 执行流进入函数, 当前环境被推入栈中(后进先出),执行完再抛掉,控制权返回到上一个执行环境, 当代码在环境中执行,会创建一个作用域链,目的是让函数与变量有序的访问,环境之间的联系是线性的,有序的,作用域链的最前端是当前代码执行的变量对象(存在当前环境的属性和方法),下一个变量对象来自包含环境,以此类推知道全局环境为止,在我们查询变量或方法的时候 只能向上搜索,我把她理解成堆积木,当代码执行在一个方法中就加一块积木,全局环境(根据宿主不同对象也不对,浏览器:window, node.js: global)就是在底层,代码只能拿到当前这块积木及其下方积木的变量,函数,但是拿不到他上方积木的变量,函数,因为它被压住了,所以没有权限,或者它的上方一无所有

没有块级作用域 :
js 只有全局作用域和局部作用域(函数), 所以在for循环 if语句中 定义的变量,在for 语句结束后 是可以访问到的

标志符解析:
js在查找标识符的时候,会现在当前环境下查找,如果找到了,就不会向上查找了,所以在当前环境中并不会调用上级环境中的同名标识符。

自己的理解:
全局作用域中的变量所有人都可以访问,局部作用域中的变量只有自己可以访问。如果局部找不到,就向上一级外部作用域访问,直到找到最后的全局作用域。

4.2.3 垃圾收集
原理:找出那些不再继续使用的变量,然后释放其占用的内存。为此,垃圾收集器会按照固定的时间间隔(或者代码执行中预定的收集时间),周期性的执行这一操作。

用于标记无用变量的策略可能会因实现而异,但是通常有以下两种:

标记清除:垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记(当然,可以使用任何标记方式)。然后,它会去除环境中的变量以及被环境中的变量引用的变量的标记。而在此之后再被标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后,垃圾收集机制器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。

引用计数(不太常用):记录每个值的被引用次数,声明一个变量,赋值了一个引用类型就+1,如果这个变量赋给别的变量再加1,如果这个值取了别的值就减1,如果减到0, 就代表无法访问了,就会被回收. 但是如果涉及到循环引用那么变量永远不可能等于0,也就永远不会被回收,所以许多厂商就放弃了这种方式, 然而在部分浏览器中(ie低版本),浏览器的一部分对象并不是js原生对象,浏览器本身的垃圾回收装置可能也采用了引用计数方式, 在操作这一部分对象时(BOM,DOM),如果循环引用了,那么也永远不会被回收

性能问题 : 垃圾处理器是周期性运行的,如果变量分配的内存数很多,回收工作量也会很大.

管理内存 : 解除引用 当数据不再有用,将其的值设置为null 来释放引用, 解除引用的真正作用是让值脱离环境,以便垃圾回收器下次运行时将其收回。

4.3 函数表达式
function createComparisonFunction(propertyName) {

        return function(object1, object2){
            var value1 = object1[propertyName];
            var value2 = object2[propertyName];
    
            if (value1 < value2){
                return -1;
            } else if (value1 > value2){
                return 1;
            } else {
                return 0;
            }
        };
    }

    var data = [{name: "Zachary", age: 28}, {name: "Nicholas", age: 29}];
    
    data.sort(createComparisonFunction("name"));
    alert(data[0].name);  //Nicholas
    
    data.sort(createComparisonFunction("age"));
    alert(data[0].name);  //Zachary        

把函数当成值来使用的情况下,都可以使用匿名函数。不过,这并不是匿名函数唯一的用途。

闭包
闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常用方式,就是在一个函数内部创建另一个函数。用上面的createComparisonFunction为例。

注意:由于闭包会携带包含它的函数作用域,因此会比其他函数占用更多的内存。过度使用闭包可能会导致内存占用过多,建议读者只在绝对必要时再考虑使用闭包。

1565614694698

闭包与变量

作用域的配置机制使得闭包只能取得包含函数中任何变量的最后一个值。闭包保存的是整个变量对象,而不是某个特殊的变量。如下:

        function createFunctions(){
            var result = new Array();
            
            for (var i=0; i < 10; i++){
                result[i] = function(){
                    return i;
                };
            }
            
            return result;
        }
        
        var funcs = createFunctions();
        
        //every function outputs 10
        for (var i=0; i < funcs.length; i++){
            document.write(funcs[i]() + "<br />");
        }

通过创建另外一个匿名函数强制让闭包的行为符合预期

        function createFunctions(){
            var result = new Array();
            
            for (var i=0; i < 10; i++){
                result[i] = function(num){
                    return function(){
                        return num;
                    };
                }(i);
            }
            
            return result;
        }
        
        var funcs = createFunctions();
        
        //every function outputs 10
        for (var i=0; i < funcs.length; i++){
            document.write(funcs[i]() + "<br />");
        }

this对象

匿名函数的执行环境具有全局性,因此其this对象同v行指向window.

    var name = "The Window";
    
    var object = {
        name : "My Object",
    
        getNameFunc : function(){
            return function(){
                return this.name;
            };
        }
    };
    
    alert(object.getNameFunc()());  //"The Window"

每个函数在被调用时,其活动对象都会自动去得两个特殊变量:this和arguments。内部函数在搜索这两个变量时,只会搜索到其活动对象为止,因此永远不可能直接访问外部函数中的这两个变量。不过,把外部作用域中的this对象保存在一个闭包能访问到的变量里,就可以让闭包访问该对象了,如下:

  var name = "The Window";
    
    var object = {
        name : "My Object",
    
        getNameFunc : function(){
            var that = this;
            return function(){
                return that.name;
            };
        }
    };
    
    alert(object.getNameFunc()());  //"The Window"

内存泄漏

https://www.jb51.net/article/78597.htm

模仿块级作用域
匿名函数可以模仿块级作用域

(function(){
//这里是块级作用域
})()
私有变量
4.4引用类型
Object类型
Array类型
创建数组

使用Array构造函数

var colors = new Array(3);
var colors = new Array(3); //create an array with three items
var names = new Array("Greg"); //create an array with one item, the string "Greg"
字面量形式

var colors = ["red", "blue", "green"]; //creates an array with three strings
var names = []; //creates an empty array
var values = [1,2,]; //AVOID! Creates an array with 2 or 3 items
var options = [,,,,,];
检测数组
instanceof 可以检测数组

value instanceof Array
但是如果网页存在多个框架 存在多个全局环境就可能会出现问题, 所以 es5 推出了 Array.isArray(list)检测到底是不是数组, ie9+支持

Array.isArray(list)
转换方法
返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串

toLocaleString()

toString()---返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串

valueOf()---返回的还是数组

var colors = ["red", "blue", "green"]; //creates an array with three strings
alert(colors.toString()); //red,blue,green
alert(colors.valueOf()); //red,blue,green
alert(colors); //red,blue,green
如果数组中 有一项为null or undefined 就用空字符串表示

join()--使用不同的分隔符来构建这个字符串,只接受一个参数,即用作分隔符的字符串

    var colors = ["red", "green", "blue"];
    alert(colors.join(","));      //red,green,blue
    alert(colors.join("||"));     //red||green||blue

其中join()方法穿参数就用 参数分割数组,不传就用默认,表示

栈方法
后进先出

push()---从数组后面插入,返回的是数字的长度

pop()----从数组后面删除,返回数组最后一个元素

    var colors = new Array();                      //create an array
    var count = colors.push("red", "green");       //push two items
    alert(count);  //2
    
    count = colors.push("black");                  //push another item on
    alert(count);  //3
    
    var item = colors.pop();                       //get the last item
    alert(item);   //"black"
    alert(colors.length);  //2

队列方法
先进先出

shift()---从数组前面移除,返回的是数组的第一项

var colors = new Array(); //create an array
var count = colors.push("red", "green"); //push two items
alert(count); //2

    count = colors.push("black");                  //push another item on
    alert(count);  //3
    
    var item = colors.shift();                     //get the first item
    alert(item);   //"red"
    alert(colors.length);  //2

unshift()---从数组前面添加,返回的是数组的长度

    var colors = new Array();                      //create an array
    var count = colors.unshift("red", "green");    //push two items
    alert(count);  //2
    
    count = colors.unshift("black");               //push another item on
    alert(count);  //3
    
    var item = colors.pop();                     //get the first item
    alert(item);   //"green"
    alert(colors.length);  //2

重排序方法
reverse()

    var values = [1, 2, 3, 4, 5];
    values.reverse();
    alert(values);       //5,4,3,2,1

sort()---按升序排列数组项,最小的值在最前面,最大的值排在最后面。为了实现排序,sort()会调用每个数组项的toString()转型方法,然后比较得到的字符串,以确定如何排序。即使数组中的每一项都是数值,sort()方法比较的也是字符串。

    var values = [0, 1, 5, 10, 15];
    values.sort();
    alert(values);    //0,1,10,15,5

由于默认的按字符串排序不是最佳方案,所以sort()可以接收一个比较函数作为参数,以便我们指定哪个值位于哪个值的前面。

比较函数接收两个参数,以下是一个简单的比较函数

   function compare(value1, value2) {
        if (value1 < value2) {
            return -1;
        } else if (value1 > value2) {
            return 1;
        } else {
            return 0;
        }
    }
    
    var values = [0, 1, 5, 10, 15];
    values.sort(compare);
    alert(values);    //0,1,5,10,15

操作方法
concat()---可以基于当前数组中的所有项创建一个新数组

    var colors = ["red", "green", "blue"];
    var colors2 = colors.concat("yellow", ["black", "brown"]);
    
    alert(colors);     //red,green,blue        
    alert(colors2);    //red,green,blue,yellow,black,brown

slice()---基于当前数组中的一个或多个项创建一个新数组,可以接收一个或两个参数,即要返回项的起始和结束位置。返回数组的项在结束位置之前,不包含结束位置, 如果有参数为负数,那么实际就是用数组长度去加上这个负数,如果结束位置小于起始位置,则返回空数组,不改变原数组

    var colors = ["red", "green", "blue", "yellow", "purple"];
    var colors2 = colors.slice(1);
    var colors3 = colors.slice(1,4);
    
    alert(colors2);   //green,blue,yellow,purple
    alert(colors3);   //green,blue,yellow

splice()----像数组的中部插入项,返回一个数组,该数组包含从原始数组中删除的项(如果没有删除任何项,则返回一个空数组)

删除 Splice(0,2)会删除数组中的前两项,参数为要删除的第一项的位置和要删除的项数

插入 Splice(2,0,"red","green")会从当前数组的位置2开始插入字符串“red”和“green”,参数主要为三个:起始位置,0(要删除的项数)和要插入的项

替换 Splice(2,1,"red","green")会删除当前数组位置2的项,然后再从位置2开始插入字符串“red”和“green”

var colors = ["red", "green", "blue"];
var removed = colors.splice(0,1); //remove the first item
alert(colors); //green,blue
alert(removed); //red - one item array

removed = colors.splice(1, 0, "yellow", "orange"); //insert two items at position 1
alert(colors); //green,yellow,orange,blue
alert(removed); //empty array

removed = colors.splice(1, 1, "red", "purple"); //insert two values, remove one
alert(colors); //green,red,purple,orange,blue
alert(removed); //yellow - one item array
位置方法
indexOf()

LastIndexOf()

这两个方法都接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。indexOf()从数组的开头(位置0)向后查找,LastIndexOf()方法则从数组的末尾开始向前查找。

返回的是参数所在位置

    var numbers = [1,2,3,4,5,4,3,2,1];
    
    alert(numbers.indexOf(4));        //3
    alert(numbers.lastIndexOf(4));    //5
    
    alert(numbers.indexOf(4, 4));     //5
    alert(numbers.lastIndexOf(4, 4)); //3       

    var person = { name: "Nicholas" };
    var people = [{ name: "Nicholas" }];
    var morePeople = [person];
    
    alert(people.indexOf(person));     //-1
    alert(morePeople.indexOf(person)); //0

迭代方法
every()

some()

forEach()---用于调用数组的每个元素,并将元素传递给回调函数 numbers.forEach(myFunction)

button onclick="numbers.forEach(myFunction)">点我

数组元素总和:

filter()----创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。

map()----返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。按照原始数组元素顺序依次处理元素。

[[1, 2], [3, 4]].map(([a, b]) => a + b);// [ 3, 7 ]
var list = [1, 2, 3, 4, 5, 6];

  //every 运行指定函数 如果每一项都为true都为 则返回true 否则 返回 false
  var result = list.every(function(item, index, array) {
    return item > 1;
  });
  console.log(result); // false

  //some 运行指定函数 如果只要有一项都为true 则返回true 否则 返回 false
  result = list.some(function(item, index, array) {
    return item > 1;
  });
  console.log(result); // true

//filter 运行指定函数 返回值为true 当前项推入新数组 返回一个新数组
  result = list.filter(function(item, index, array) {
    return item > 1;
  });
  console.log(result); // [2, 3, 4, 5, 6]

  //map 运行指定函数 把函数运行结果 推入数组 返回一个新数组
  result = list.map(function(item, index, array) {
    return item * 10;
  });
  console.log(result); // [10, 20, 30, 40, 50, 60]

   //forEach 仅仅运行指定函数 没有返回值 也不能使用 continue break 跳出循环会报错
  result = list.forEach(function(item, index, array) {
     if (item > 1) {
       return // 会跳出当前循环 类似 continue的效果
     }
  });
  console.log(result); // undefined

缩小方法
reduce()

reduceRight()

迭代数组 执行指定函数 最终返回一个值, 参数(上一个值,当前项,索引,原数组), reduce的迭代是从第二项开始的, 当第一次循环时 index的值为1 pre就等于array[0] cur等于array[1],当第二次循环时pre 等于之前函数的返回值

  var list = [1, 2, 3, 4, 5, 6];

  var result = list.reduce(function(pre,cur,index,array){
    return pre + cur;
    console.log(index); // 1,2,3,4,5
  })
  console.log(result); // 21

es6方法
拓展运算符
扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。

console.log(...[1, 2, 3])
// 1 2 3

console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
该运算符主要用于函数调用。

function push(array, ...items) {
array.push(...items);
}

function add(x, y) {
return x + y;
}

const numbers = [4, 38];
add(...numbers) // 42
替换函数的apply方法

Array.from
用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)。

Array.of
方法用于将一组值,转换为数组。

fill()
使用一个值,填充数组

Function方法
函数属性和方法
属性

length----函数希望接收的命名参数的个数

prototype----保存它们所有实例方法的真正所在

方法

这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值

apply()----接收两个参数,一个是在其中运行函数的作用于,另一个是参数数组,第二个可以是Array的实例,也可以是arguments对象,例如:

    function sum(num1, num2){
        return num1 + num2;
    }
    
    function callSum1(num1, num2){
        return sum.apply(this, arguments);
    }
    
    function callSum2(num1, num2){
        return sum.apply(this, [num1, num2]);
    }
    
    alert(callSum1(10,10));   //20
    alert(callSum2(10,10));   //20

callSum1()在执行sum()函数时传入了this作为this值(因为是在全局作用域中调用的,所以传入的就是window对象)和arguments。而callSum2()同样也调用了sum()函数,但它传入的则是this和一个参数数组。

call()----和apply基本相同,变化的是传递给函数的参数必须逐个列举出来

    function sum(num1, num2){
        return num1 + num2;
    }
    
    function callSum(num1, num2){
        return sum.call(this, num1, num2);
    }
    
    alert(callSum(10,10));   //20

传递参数并不是apply()和call()真正的用处,他们真正强大的是能够扩充函数赖以运行的作用于。

    window.color = "red";
    var o = { color: "blue" };
    
    function sayColor(){
        alert(this.color);
    }
    
    sayColor();            //red
    
    sayColor.call(this);   //red
    sayColor.call(window); //red
    sayColor.call(o);      //blue

bind()---会创建一个函数的实例,其this值会被绑定到传给bind函数的值。

    window.color = "red";
    var o = { color: "blue" };
                       
    function sayColor(){
        alert(this.color);
    }
    var objectSayColor = sayColor.bind(o);
    objectSayColor();   //blue

关于apply(),call()的一些问题---重点理解。
apply和call都是调用本身没有但是其他对象方法里用的方法。

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
Array.prototype.push.apply(arr1,arr2);//常见例子
这里就是arr1调用push方法,arr2是方法里面的参数。

Array.prototype.shift.call(arguments);//这句话的意思就是说获取第一个参数的值
Array.prototype.shift()删除数组的第一个元素,并返回这个元素。该方法会改变数组的长度。

function Person(name,age){
this.name = name;
this.age = age;
}

function Student(name,age,grade){
Person.apply(this,arguments);
this.grade = grade;
}
Student调用Person的方法。

4.5事件
事件流
描述的是从页面中接受事件的顺序

事件冒泡

ie的事件流叫做事件冒泡。事件开始由最具体的元素(目标元素) 直至不具体的节点(文档), 事件会依次传播,例如点击一个div,click事件会传递到他的父级直到document或window,所有浏览器都支持事件冒泡

事件捕获

事件捕获与冒泡相反,不具体节点先接收事件,具体节点在最后接收事件,它的寓意在于事件在到达预定目标之前捕获他

DOM事件流

DOM2级规定了事件流包括三个阶段 事件捕获, 处于目标阶段, 事件冒泡阶段,

1565616520477

事件处理程序
事件就是用户或浏览器自身执行的某种动作。比如click.而响应某个事件的函数就叫做事件处理程序(或事件侦听器)。

html事件处理程序

<input type="button" value="Click Me" onclick="showMessage()" />

function showMessage(){
alert("Hello world!");
}
DOM0级事件处理程序

    var btn = document.getElementById("myBtn");
    btn.onclick = function(){
        alert(this.id);//"myBtn"
    };
    
    var removeBtn = document.getElementById("myRemoveBtn");
    removeBtn.onclick = function(){
        btn.onclick = null;//删除事件处理程序
    };

DOM2级事件处理程序

定义了两个方法

addEventListener()

removeEventListener()

他们都接收三个参数,要处理的事件名,作为事件处理程序的函数和一个布尔值。布尔值为true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。

    var btn = document.getElementById("myBtn");
    btn.addEventListener("click", function(){
        alert(this.id);
    }, false);
    btn.addEventListener("click", function(){
        alert("Hello world!");
    }, false);

通过addEventListener添加的事件只能使用removeEventListener来移除,移除时传入的参数与添加处理程序时使用的参数相同。

    var btn = document.getElementById("myBtn");
    var handler = function(){
        alert(this.id);
    };
    btn.addEventListener("click", handler, false); 
    
    var removeBtn = document.getElementById("myRemoveBtn");
    removeBtn.onclick = function(){
        btn.removeEventListener("click", handler, false);  //works!
    };

IE事件处理程序

跨浏览器事件处理程序

事件对象
在触发DOM上的某个事件的时候,会产生event对象,这个对象包含着所有与事件有关的信息,虽然所有浏览器都支持,但方式不同, 如火狐的事件方法的参数必须传入event ,而chrome 直接在函数体中使用event就可以了

DOM事件对象

  var divClick = document.getElementById('divClick');
  var uu = document.getElementById('uu');

  divClick.onclick = function(event) {
    //是否冒泡
    console.log(event.bubbles);
    //是否可以取消默认行为
    console.log(event.cancelable);
    //表示是否调用了event.preventDefault()
    console.log(event.defaultPrevented);
    //事件阶段 1捕获 2 目标阶段 3冒泡阶段
    console.log(event.eventPhase);
    //事件的类型
    console.log(event.type); //click
    //正在执行事件的元素
    console.log(event.currentTarget); //divClick
    //触发事件的目标元素
    console.log(event.target); //divClick
    //阻止当前元素的默认事件 如a标签的跳转
    event.preventDefault();
    console.log(event.defaultPrevented); //true
    //阻止事件冒泡 点击divClick后 uu的click不会执行
    event.stopPropagation();
  };

  uu.onclick = function(event) {
    /* 
      当点击uu元素本身的时候触发click时 currentTarget = target 为uu
      但当点击uu内部元素divClick 触发click时 click方法冒泡到了uu
      此时uu执行click事件,event的currentTarget为 uu 而target 为divClick
     */
    console.log(event.currentTarget); //uu
    console.log(event.target); //divClick
  };

  /* 
     event.stopImmediatePropagation();
     不单单会阻止事件冒泡,还会阻止事件分发(在绑定多个click处理器的情况下)
     当执行 event.stopPropagation() 会打印 12 13 14
     当执行 event.stopImmediatePropagation() 会打印 12
   */

  divClick.addEventListener('click', function(event) {
    // event.stopPropagation()
     event.stopImmediatePropagation();
    console.log('12');
  });
  divClick.addEventListener('click', function(event) {
   
    console.log('13');
  });
  divClick.addEventListener('click', function(event) {
    console.log('14');
  });

注意:只有再事件处理程序执行期间,event对象才会存在;一旦事件处理程序执行完成,event对象就会被销毁。

ie事件对象

ie8及一下不支持通过传参的形式,只能通过window.event,event函数稍有不用

  divClick.onclick = function(event){
    var e = event || window.event;
    console.log(e);
    //srcElement 类似target
    console.log(e.srcElement === this);
    // 类似于 preventDefault()
    e.returnValue = false;
    //类似于 stopPropagation()
    e.cancelBubble = true
  }

事件类型
浏览器中可能发生的类型有很多种,不同类型具有不同的信息

内存和性能
在js中事件处理程序的数量, 影响着 页面的整体性能, 每个函数都是对象, 内存中对象越多,性能就越差.

事件委托

解决事件处理程序过多。利用事件冒泡,使用事件事件委托,只需在DOM树中尽量最高的层次上添加一个事件处理程序。

  /* 
    可以给父元素绑定事件
    当子元素触发相同事件时 冒泡到父元素
    父元素根据子元素类型 来判断如何执行
   */
  uu.onclick =function(event){
    console.log(event.target)
  }

采用这种方式的优点:https://www.cnblogs.com/xiayu25/p/6269652.html

移除事件处理程序

在删除dom元素后, 事件处理程序极有可能不会被释放 , 可以在删除元素之前, 删除方法

模拟事件
4.6 高级技巧
高级函数
call函数详解 https://blog.csdn.net/ithanmang/article/details/83411831

Object.prototype.toString.call()
深入理解Object.prototype.toString.call() https://www.jianshu.com/p/e4237ebb1cf0

4.7 ajax
XMLHttpRequest对象
function createXHR(){
if (typeof XMLHttpRequest != "undefined"){
return new XMLHttpRequest();
} else if (typeof ActiveXObject != "undefined"){
if (typeof arguments.callee.activeXString != "string"){
var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
"MSXML2.XMLHttp"],
i, len;

                for (i=0,len=versions.length; i < len; i++){
                    try {
                        new ActiveXObject(versions[i]);
                        arguments.callee.activeXString = versions[i];
                        break;
                    } catch (ex){
                        //skip
                    }
                }
            }
        
            return new ActiveXObject(arguments.callee.activeXString);
        } else {
            throw new Error("No XHR object available.");
        }
    }
    
    var xhr = createXHR();        
    xhr.open("get", "example.txt", false);
    xhr.send(null);
    
    if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
        alert(xhr.statusText);
        alert(xhr.responseText);
    } else {
        alert("Request was unsuccessful: " + xhr.status);
    }

XHR的用法

检测XHR对象的readyState属性,该属性表示请求/响应过程的当前活动状态。

    var xhr = createXHR();        
    xhr.onreadystatechange = function(event){
        if (xhr.readyState == 4){
            if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
                alert(xhr.responseText);
            } else {
                alert("Request was unsuccessful: " + xhr.status);
            }
        }
    };
    xhr.open("get", "example.txt", true);
    xhr.send(null);

HTTP头部信息

GET请求

POST请求

进度事件
1565791365838

跨域资源共享
CORS(Cross-origin Resource Sharing,跨源资源共享)是W3C的一个工作草案,定义了在必须访问跨源资源时,浏览器与服务器应该如何沟通。CORS背后的基本思想,就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功。还是应该失败。

1565791632234

其他跨域技术
图像ping

使用标签。一个网页可以从任何网页中加载图像,不用担心跨域问题不跨域。这是在线广告跟踪浏览量的主要方式。

jsonp

jsonp看起来和json差不多,只不过是被包含在函数调用中的json

callback({"name":"Nicholas"});
由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数。回调函数的名字一般是在请求中指定的。而数据就是传入回调函数中的json数据。下面是一个典型的jsonp请求:

http://freegeoip.net/json/?callback=handleResponse
jsonp是通过动态

原文地址:https://www.cnblogs.com/zhoujingguoguo/p/11540108.html