面试题-JS
原型链
==与===的区别
==用于比较、判断两者相等,在比较的时候可以自动转换数据类型
===用于严格比较、判断两者严格相等,比较时不会进行自动转换,要求进行比较的数据类型必须一致,否则返回false
强制类型转化和隐式类型转换
强制类型转换:【parselInt、parseFloat、number】
隐式类型转换:【==、===】
JS的六大数据类型
Number、String、Boolean、Null、undefined、Onject
typyof 123 //Number
typeof '123' //String
typeof true //Boolean
typeof undefined //undefined
typeof Null //Object
typeof {} //Object
typeof [] //Object
typeof console.log() //Function
null类型进行typeof操作符后,结果是object,因为null类型被当作空对象引用。
1、Number类型
Number包括整数和浮点数两个值。
NAN:非数字类型。特点:涉及到的任何关于NAN操作返回值都是NAN、NAN不等于自身。
isNAN用于检查其参数是否为非数字值。
2、String
字符串具有length属性
字符串转换:转型函数String(),适用于任何数据类型(null,undefined 转换后为null和undefined);toString()方法(null,defined没有toString()方法)。
3、Boolean【true、false】
4、undefined
只有一个undefined值,var声明变量,但是未给变量初始化值,那么这个变量的值就是undefined。
【拓展】void
#无论void后面的表达式是什么,void 操作符都会返回 undefined
#为什么不直接用 undefined
因为 undefined 在js中不是保留字
function joke() {
var undefined = 'hello world';
console.log(undefined) // hello world
}
console.log(undefined) // undefined
你可以在函数上下文内以 undefined 作为变量名,于是在这个上下文写的代码便只能通过从全局作用域取到 undefined,如:
window.undefined //浏览器环境
GLOBAL.undefined //node环境
但是注意的是,即使 window,GLOBAL 仍然可以在函数上下文被定义,故从 window/GLOBAL 上取 undefined
并不是100%可靠的做法。如:
function x() {
var undefined = 'hello world',
f = {},
window = {
'undefined': 'joke'
}
console.log(undefined) //hello world
console.log(window.undefined) //joke
console.log(f.a === undefined); //false
console.log(f.a === void 0) //true
}
#采用 void 方式获取 undefined 便成了通用准则【如 underscore.js里的isUndefined便是这么写的】
#除了 void 方式获取 undefined 还有通过一种函数调用的方法【AngularJs源码】:
(function(window, document, undefined) {
//.....
})(window, document);
通过不穿参,确保 undefined 参数的值是一个 undefined
#其他作用:填充href。
&比如微博有转发、收藏、评论等都是超链接,但是用户并不希望点击他们会跳转到另一个页面,而引发的一些交互操作。
理论上,这三个超链接都是没有url的,如果不写的话,点击会刷新整个页面。于是使用了 href="javascript:void(0)"的方式,确保点击它会执行一个没用的 void(0)
&另一种情况是,如果我们要生成一个空的src的image,最好的方式也是src="javascript:void(0)"
*总结:void有如下作用:
通过采用void 0取undefined比采用字面上的undefined更靠谱更安全,应该优先采用void 0这种方式。
填充<a>的href确保点击时不会产生页面跳转; 填充<image>的src,确保不会向服务器发出垃圾请求。
5、null
null类型被看作空对象指针,前面说到null也是空的对象引用。
6、Object
js中对象是一组属性与方法的集合。这里就要说到引用类型了,引用类型是一种数据结构,用于将数据和功能结合到一起。引用类型有时候也被称为对象定义。因为他们描述的是一类对象所具有的属性和方法。
三大引用类型
1、Object类型
我们看到的大多数类型值都是Object类型的实例,创建Object实例的方式有两种。
第一种是使用new操作符后面跟Object构造函数:
var obj = new Object();
obj.name = 'an';
第二种是使用对象字面量表示法:
var obj = {
name = 'an',
sex: 'man'
}
2、Array类型
数组的每一项可以用来保存任何类型的数据,也就是说,可以用数据的第一个位置来保存字符串,第二个位置保存数值,第三个位置保存对象...另外,数组的大小是可以动态调整的。
创建数组的方式有两种:
第一种是使用Array构造函数:
var arr = new Array(1,2,3)
第二种是使用数组字面量表示法:
var arr =[1,2,3];
3、Function类型
每个函数都是function类型的实例,而且与其他引用类型一样具有属性和方法。函数通常使用函数声明语法定义的:
function sum(a,b){
return a + b;
}
var sum = function(){
return a + b;
}
也就是说,js按照存储方式分为值类型和引用类型,那么他们的计算有什么区别呢?
var a = 100;
var b = a;
a = 200;
console.log(b) //100
简单的值类型,在从a变量向b变量赋值基本类型时,会在b变量上创建一个坑位,然后在把a值复制给b坑位。
var a = {age: 20};
var b = a;
b.age = 22;
console.log(a.age); //22
引用类型,当从一个变量向另一个变量赋值引用类型时,同样也会将存储在变量中对象的值复制一份放到为新变量分配的空间中。
实现add(1)(2)(3)【柯里化:(部分求值),简单来说就是只传递给函数一部分参数来调用它,让他返回一个函数去处理剩下的参数。】
var add = function(a,b,c) {
return a+b+c
}
var add = function(a) {
return function(b) {
return function(c) {
return a+b+c;
}
}
}
JS处理数组的方法[参考文章内容]
一、迭代方法
ES5为数组定义了五个迭代方法:
1、every[与some相反]
对数组每一项进行给定函数,如果每一项都返回true,则返回true
var arr = [1,2,3,2,1];
var getArr = arr.every(function(item,index,array){
return item > 2;
})
console.log(getArr); //false
2、some[与every相反]
对数组每一项进行给定函数,如果其中任意一项返回true,则返回true
var arr = [1,2,3];
var getArr = arr.some(function(item,index,array){
return item>2;
})
console.log(getArr); //true
3、filter
对数组每一项进行给定函数,返回该数组会返回true的项形成的数组
var arr = [1,2,3,2,1];
var getArr = arr.filter(function(item,index,array){
return item>2;
})
console.log(getArr); //[3]
4、map
对数组每一项进行给定函数,返回每次函数调用的结果组成的数组
var arr = [1,2,3,2,1];
var getArr = arr.map(function(item,index,array){
return item+2;
})
console.log(getArr); //[2,3,4,3,2]
5、forEach
对数组每一项进行给定函数,没有返回值,和for循环类似。
var arr = [1,2,3,2,1];
arr.forEach(function(item,index,array){
console.log(index) //1,2,3,4,5
})
二、归并方法
ES5新增了两个归并方法:reduce()和reduceRight()。这两个方法迭代数组所有项,然后构建一个最终返回的值。reduce从左到右,reduceRight反之。
var arr = [1,2,3,4,5];
var getArr = arr.reduce(function(perv,cur,index,array){
return prev+cur;
})
console.log(getArr); // 15
reduce函数接受四个参数:前一个值、当前值、index和数组对象这个数组返回的任何值都会作为第一个参数自动传给下一项。
三、检测数组
ES3的方法:instanceof
var arr = [1,2,3];
if(arr instanceof Array){
//对数组进行某些操作
}
ES5的方法:Array.isArray
var arr = [1,2,3];
if(Array.isArray(arr)) {
//对数组进行某些操作
}
四、转换方法
1、toLocaleString()、toString()、valueOf()
2、join将数组转换为字符串,且用分隔符分割
var arr = [1,2,3];
console.log(arr.join('|')); //1|2|3
五、栈方法
push()从数组末尾添加
pop()从数组末尾移除
六、队列方法
shift()从数字前端移除
unshift()从数组前端添加
七、重序列方法
reverse()反转数组
sort()排序
var arr = [1,2,3,4,5];
arr.sort(function(a,b){
return b-a; //降序[5,4,3,2,1]
return a-b; //升序[1,2,3,4,5]
})
八、操作方法
1、concat()用于复制或者从尾部添加=>创建新数组
var arr = [1,2,3];
var arr1 = arr.concat(4); //[1,2,3,4]
2、slice()用于复制或截取数组=>创建新的数组
截取当前数组的一部分创建一个新的数组。可以接受一个或两个参数,只有一个参数时返回指定位置到尾部的数组。
var arr = [1,2,3];
console.log(arr.slice()) //[1,2,3]
console.log(arr.slice(1)) //[2,3]
console.log(arr.slice(1,2)) //[2]
3、splice()用于删除、插入、替换,号称最强大的数组方法
3.1、删除:可以删除任意数量的项,需要两个参数,要删除的第一项的位置和最后一项位置;
var arr = [1,2,3];
arr.splice(0,2) //[1,2]
console.log(arr) //[3]
3.2、插入和替换:至少三个参数,第一个是起始位置,第二个是要删除的项,第三个及以后是要插入或替换的位置;
//插入demo:
var values = [1,2,3,4,5,6];
var v1 = values.splice(1,0,1,1,1);
console.log(values); //[1,1,1,1,2,3,4,5,6]
console.log(v1); //[]
//替换demo:
var values = [1,2,3,4,5,6];
var v1 = values.splice(1,2,1,1,1);
console.log(values); //[1,1,1,1,4,5,6]
console.log(v1); //[2,3]
九、位置方法
var arr = [1,2,3];
arr.indexOf(1)
字符串api传送门
1、三个字符方法
var str = 'abc';
str.charAt(1) //b
str.charCodeAt(1)
str[1] //b
2、4个字符串操作方法
var str = 'abc';
str.concat('c') //'abcc'
slice()、substr()、stbstring()区别:
接受一个或两个参数:开始位置/结束位置
slice()/substring()第二个参数是结束字符后面的位置,substr()第二个参数是返回字符的个数
slice()传入的负值与字符串的长度相加
substr()第一个参数加上字符串的长度,第二个将负数转化为0
substring()所有负值转化为0
3、字符串位置方法
indexOf()、lastIndexOf()
前者从前往后搜索、后者从后往前搜索
第一个参数为搜索的元素,第二个参数指定从字符串的哪个位置开始搜索
4、trim()方法
该方法删除前置和后缀的所有空格,然后返回
5、4个字符串大小写转换
toLowerCase()/toLocaleLowerCase()/toUpperCase()/toLocaleUpperCase()
6、4个字符串的模式匹配方法
1)match()方法:本质上与调用RegExp的exec()方法相同。只接受一个参数,要么是一个正则表达式,要么是一个RegExp对象。
返回值:,返回的是数组。数组第一项是与整个模式匹配的字符串,之后的每一项保存着与正则表达式中捕获组匹配的字符串。
var text ="cat,bat,sat,fat";
var pattern =/.at/;
var matches = text.match(pattern);
console.log(matches);//[ 'cat', index: 0, input: 'cat,bat,sat,fat' ]
console.log(matches.index);//0
console.log(matches[0]);//cat
console.log(pattern.lastIndex);//0
补充RegExp对象的主要方法:exec()
注意:对于exec(),即使在模式中设置了全局标志(g),它每次也只返回一个匹配项,在不设置全局标志时,在同一个字符串上多次调用exec()将始终返回第一个匹配项的信息。而在设置全局标志时,每次调用exec()都会在字符串中继续查找新匹配项,直到所搜到字符串末尾为止。还有注意lastIndex属性的变化情况。在全局模式下,lastIndex属性在每次调用exec()后都会增加,而在非全局模式则始终不变。
RegExp对象的test()方法:
接受一个字符串参数,模式与该参数匹配返回true,否则返回false。经常被用在if语句中。
(2)search()方法:
该方法也是一个参数,与match()方法参数相同。
返回字符串中第一个匹配项的索引。如果没有找到匹配项,则返回-1。
(3)replace()方法
该方法有两个参数:第一个参数是一个RegExp对象或者一个字符串,第二个参数可以是一个字符串或者函数。如果第一个参数是字符串,那么只会替换第一个子字符串。如果要替换所有的子字符串,就是提供一个正则表达式,而且指定全局(g)标志。
如果第二个参数是函数,在只有一个匹配项时,会向该函数传递3个参数:模式的匹配项,模式匹配项在字符串中的位置和原始字符串。如果正则表达式中定义了多个捕获组,传递的参数:模式的匹配项、第一个捕获组的匹配项、第二个捕获组的匹配项……,但最后两个参数还是模式匹配项在字符串中的位置和原始字符串。使用函数作为第二个参数可以实现更为精细的替换操作。
(4)split方法
可以基于分隔符将一个字符串分成多个子字符串,并放入数组中。其中分隔符可以是字符串,也可以是RegExp对象。还可以接受第二个参数,用于指定数组的大小,确保返回的数组不会超过既定大小。
HTML-超文本标记语言
贯穿整个页面
CSS-层叠 样式表
三种声明方式
【外联样式表】在head标签中,用link标签的href属性来引用后缀名.css的css样式文件
【内联样式表】在head标签下的style标签中,选择器+样式声明
【内部样式表】在标签的style属性中,添加css样式声明
JavaScript-解释性脚本语言【JavaScript有自己专门的解释器-JavaScript引擎,它存在于浏览器端,作为浏览器的一部分】
在script标签中,可以在head标签中,也可以在body标签中。
从上到下运行,先解析head标签中的代码:
HTML页面加载顺序http与https
http与https的基本概念
HTTP【超文本传输协议】是互联网上应用最广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准【TCP】,用于www服务器传输超文本到本地浏览器的传输协议它可以是浏览器更加高效,使网络传输减少。
HTTPS,是以安全为目的的HTTP通道,简单来说就是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详情内容就需要SSL。【HTTPS=HTTP+SSL】
HTTPS的主要作用可以分为两种:一种是建立一种信息安全通道,来保证数据传输的安全。另一种是确认网站的真实性。
HTTPS与HTTP的主要区别:
1、HTTPS需要申请证书,一般免费证书比较少,因此需要一定费用;
2、http是超文本传输协议,信息是明文的,HTTPS则是具有安全性的ssl加密传输协议;
3、http与https使用完全不同的连接方式,用的端口也不一样,前者80,后者443;
4、http的连接很简单,是无状态的;https协议是ssl+http协议构建的可进行加密传输、身份认证的网络传输,比http协议安全。
HTTPS缺点:
1、HTTPS协议握手阶段比较费时,会使页面的加载时间延长近50%,增加耗电;
2、https连接缓存不如http高效,会增加数据开销和功耗,甚至已有的安全措施也会因此而受到影响;
3、SSL证书需要钱,功能越强大的证书费用越高,个人网站、小网站没有必要一般不会用;
4、SSL证书通常需要绑定IP,不能在同一IP上绑定多个域名,IPv4资源不可能支撑这个消耗;
5、HTTPS协议的加密范围也比较有限,在黑客攻击、拒绝服务攻击、服务器劫持等方面几乎起不到什么作用。最关键的,SSL证书的信用链体系并不安全,特别是在某些国家可以控制CA根证书的情况下,中间人攻击一样可行。
HTTPS与HTTP图解对于浏览器缓存来说,客户端缓存分为三种:
1、不发送任何请求,直接从缓存中取数据。代表的特性:Expries、Cache-Control=<number! =0>和appcache;
2、发送请求确认是否新鲜,再决定是否返回304并从缓存中取数据。代表的特性:Last-Modified/If-Modified-Since,Etag/If-None-Match;
3、直接发送请求,没有缓存。代表的特性:Cache-Control:max-age=0/no-cache。
为什么使用缓存:
1、减少网络带宽资源;
2、降低服务器压力;
3、减少网络延迟,加快页面打开速度。
浏览器端的缓存机制:链接
对于浏览器端的缓存来讲,这些规则是在HTTP协议头和HTML页面的Meta的标签中定义的。他们分别从新鲜度和校验值两个纬度来规定浏览器是否可以直接使用缓存中的副本,还是需要去源服务器获取更新的版本。
新鲜度【过期机制】:也就是缓存副本的有效期。一个缓存副本必须满足一下条件,浏览器会认为她是有效的:
1、含有完整的过期时间控制头信息【http协议报头】,并且仍在有效期;
2、浏览器已经使用过这个缓存副本,并且在一个会话中已经检查过新鲜度;
满足以上两种情况的一种,浏览器会直接从缓存中获取副本并渲染。
校验值【验证机制】:服务器返回资源的时候,有时会在控制头信息带上这个资源的实体标签Etag(Entity Tag),它可以用来做浏览器再次请求过程中的校验标识。如果发现校验标识不匹配,说明资源已经被修改或过期,浏览器需要重新获取资源信息。
HTML5-离线缓存【Application Cache】链接
垂直居中传送门
flex布局、绝对定位+负边距、绝对定位+transform、绝对定位+marginauto等
移动端Retina屏边线1px显示为2px的问题解决办法传送门
在开发移动端web项目时,经常遇到设置broder:1px,但是显示的边框是2px,这是因为设备像素比devicePixelRatio为2引起的。
设备像素比:
设备上物理像素和设备独立像素的比例。
window.devicePixelRatio = 物理像素 / dips dip或dp【device independent pixels,设备独立像素】与屏幕密度有关。dip可以用来辅助区分视网膜设备还是非视网膜设备。
解决办法:通过背景模拟边框线,把1px一分为二
数组中最大值与最小值
1、排序法
2、假设法
假设当前数组中的第一个值为最大值,然后拿这个最大值和后面的项逐一比较,然后后面的某一直比假设的值大,说明假设错了,我们把假设的值进行替换,最后得到的结果就是我们想要的值。
var arr = [1,3,5,11,32];
var max = arr[0];
for(var i=0;i<arr.length;i++){
var cur = arr[i];
cur>max ? max=cur : null
}
console.log(max); //32
3、使用 Math 中的 max/min 方法【可以使用apply来实现,apply传入的是一个数组。】
var arr = [1,2,3];
var max = Math.max.apply(null,arr);
var min = Math.min.apply(null,arr);
4、使用ES6的扩展运算符
var arr = [1,2,3];
var max = Math.max(...arr);
rem产生的小数像素问题
rem是指相对于根元素的字体大小的单位,简单来说他就是一个相对单位。
但是由于屏幕分辨率的不同,导致出现小数像素的现象:
浏览器在渲染时所做的舍入处理只是应用在元素的渲染尺寸上,其真实占据的空间依旧是原始大小;也就是说一个元素尺寸为0.65px,那么其渲染的尺寸为1px,空出的0.35px空间由其临近的元素填充;如果一个元素尺寸为0.35px,其渲染尺寸为0px,但是其会占据临近的0.35px的空间。
问题:
目前遇到的最多的问题就是background-image的问题,经常因为小数像素导致背景图被裁掉一部分。
结局办法:
-使用iconfont;
-如果使用background-image,尽量为背景图设置一定的空白间隙