toPrecision 和 toFixed 和 Math.round 的区别?
toPrecision 用于处理精度,精度是从左至右第一个不为 0 的数开始数起。
toFixed 是对小数点后指定位数取整,从小数点开始数起。
Math.round 是将一个数字四舍五入到一个整数。
多种运算符
逗号运算符
逗号操作符对它的每个操作数求值(从左到右),并返回最后一个操作数的值。
expr1, expr2, expr3...
会返回最后一个表达式 expr3 的结果,其他的表达式只会进行求值。
function reverse(arr) {
return [arr[0], arr[1]]=[arr[1], arr[0]], arr[0] + arr[1]
}
const list = [1, 2]
reverse(list) // 返回 3,此时 list 为[2, 1]
零合并操作符 ??
零合并操作符 ?? 是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回右侧操作数,否则返回左侧操作数。
expr1 ?? expr2
|| 是一个布尔逻辑运算符,左侧的操作数会被强制转换成布尔值用于求值。任何假值(0, '', NaN, null, undefined)都不会被返回。这导致如果你使用 0、''、NaN 作为有效值,就会出现不可预料的后果。
undefined || 'default' // 'default'
null || 'default' // 'default'
false || 'default' // 'default'
0 || 'default' // 'default'
undefined ?? 'default' // 'default'
null ?? 'default' // 'default'
false ?? 'default' // 'false'
0 ?? 'default' // 0
可选链操作符 ?.
?. 操作符的功能类似于 . 链式操作符,不同之处在于,在引用为 null 或者 undefined 的情况下不会引起错误,该表达式短路返回值是 undefined。
?. 操作符允许读取位于连接对象链深处的属性的值,而不必验证链中的每个引用是否有效。
当尝试访问可能不存在的对象属性时,可选链操作符将会使表达式更短、更简明。
- 当调用不存在的对象的属性
const obj = {
a: 'foo',
b: {
c: 'bar'
}
}
obj.b?.c // bar
obj.d?.c // undefined
obj.d // undefined
以前可能会通过 obj && obj.a && obj.a.b 来获取一个深度嵌套的子属性,现在可以直接 obj?.a?.b 即可
- 当调用不存在的数组
obj.arr?.[index] //undefined
obj.arr[index] //报错
let a = [1,2,3]
a[6]?.v //undefined
a[6].v //报错
- 当调用不存在的函数
obj.fun?.() //undefined
obj.fun() //报错
有符号左移操作符 <<(位运算符 )
parseInt('ffffff', 16) = 16777215,而16777215刚好为2^24 - 1
1<<24 == 16777216
通过Math.random()*(1<<24)可以得到0~16777216之间的随机数
[].forEach.call($$("*"),function(a){
a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16)
})
(1)选取页面所有 DOM 元素。在浏览器的控制台中可以使用$$()方法来获取页面中相应的元素,这是现代浏览器提供的一个命令行 API 相当于 document.querySelectorAll 方法。
(2)循环遍历 DOM 元素
(3)给元素添加 outline 。由于渲染的 outline 是不在 CSS 盒模型中的,所以为元素添加 outline 并不会影响元素的大小和页面的布局。
(4)只需要整数部分,使用取反操作符 ~ 连续两次取反获得整数部分,然后再用 toString(16) 的方式,转换为一个十六进制的字符串。
有符号右移操作符>> (位运算符 )
将第一个操作数向右移动指定的位数,多余的位移到右边被丢弃,高位补其符号位,正数补 0,负数则补 1。因为新的最左位与前一个最左位的值相同,所以符号位(最左位)不会改变。
一般用 有符号右移操作符>> 来将一个数除 2,相当于先舍弃小数位然后进行一次 Math.floor
10 >> 1 // 5
13 >> 1 // 6 相当于
13.8 >> 1 // 6
-13 >> 1 // -7 相当于
-13.8 >> 1 // -7
无符号右移操作符 >>>(位运算符 )
将符号位作为二进制数据的一部分向右移动,高位始终补 0,对于正整数和算数右移没有区别,对于负数来说由于符号位被补 0,成为正数后就不用再求补码了,所以结果总是非负的。即便右移 0 个比特,结果也是非负的。
0b111>>>1 //3
(0b111>>>1).toString(2) // "11"
此处注意toString()的写法,前面数字必须带括号,toString(2)是转换成二进制
(4).toString(2) // '100'
4.toString(2) //报错
位运算符 &
判断奇偶数可以使用 & 1,正负数都适应
原理:使用 & 1,来判断二进制数的最低位是不是 1,这样除了最低位之外都被置 0,取余的结果只剩最低位。
const a = 5
!!(a & 1) // true
!!(a % 2) // true
位运算符 |
可以对一个数字 | 0 来取整,负数也同样适用
原理:使用位运算符时会抛弃小数位,我们可以利用这个特性来给数字取整,比如给任意数字 & 上二进制的 32 个 1,或者 | 上 0,显而易见后者简单些。
1.3 | 0 // 1
-1.9 | 0 // -1
双位运算符 ~~
替代正数的 Math.floor( ),替代负数的 Math.ceil( )。双否定位操作符的优势在于它执行相同的操作运行速度更快。
~~4.5 // 4
Math.floor(4.5) // 4
Math.ceil(4.5) // 5
~~-4.5 // -4
Math.floor(-4.5) // -5
Math.ceil(-4.5) // -4
undefined 与 undeclared 的区别?
已在作用域中声明但还没有赋值的变量,是 undefined 的。相反,还没有在作用域中声明过的变量,是 undeclared 的。
对于 undeclared 变量的引用,浏览器会报引用错误,如 ReferenceError: b is not defined 。但是我们可以使用 typeof 的安全防范机制来避免报错,因为对于 undeclared(或者 not defined )变量,typeof 会返回 "undefined"。
null 和 undefined 的区别?
-
Undefined 和 Null 都是基本数据类型,这两个基本数据类型分别都只有一个值,就是 undefined 和 null。
-
undefined 代表的含义是未定义,null 代表的含义是空对象(尚未创建的对象)。
-
一般变量声明了但还没有定义的时候会返回 undefined,null主要用于赋值给一些可能会返回对象的变量,作为初始化。
undefined 在 js 中不是一个保留字,这意味着我们可以使用 undefined 来作为一个变量名,这样的做法是非常危险的,它会影响我们对 undefined 值的判断。但是我们可以通过一些方法获得安全的 undefined 值,比如说 void 0。
- typeof undefined/null
typeof undefined //"undefined"
typeof null // "object" 这是一个历史遗留的问题,在JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null 代表的是空指针(大多数平台下值为 0x00),因此,null的类型标签也成为了 0,typeof null就错误的返回了”object”。在ES6中,当时曾经有提案为历史平凡, 将type null的值纠正为null, 但最后提案被拒了,所以还是保持”object”类型。
- == 和 ===
null == undefined //true
null === undefined //false
- 如何判断null和undefined?
- null使用严格相等符===或不相等操作符!==判断
- undefined使用严格相等符===或不相等操作符!== 和 typeof
- Number(null/undefined)
-
Number(null) // 0
-
Number(undefined) // NaN
- 用处 null的使用:
- 如果定义的变量在将来用于保存对象,那么最好将该变量初始化为null
- 当一个数据不再需要使用时,我们最好通过将其值设置为null来释放其引用,这个做法叫做解除引用
undefined:变量最好初始化,否则会等于undefined
Number()、parseInt() 和 parseFloat() 的区别
1. 如果是数字值
- Number() 和 parseFloat() 只是简单的传入和返回。
- parseInt() 根据基模式取整
Number(1.1); //1.1
parseInt(1.1) // 1
parseFloat(1.1) // 1.1
处理整数的时候parseInt()更常用
. 如果是字符串
-
parseInt()和parseFloat()相同点:在转换字符串时,会忽略字符串前面的空格,直到找到第一个非空格字符,如果第一个字符是数字字符,会继续解析第二个字符,直到解析完所有后续字符串或者遇到了一个非数字字符,如果第一个字符不是数字或者负号, 就会返回NaN,同样的,转换空字符串也会返回NaN。
-
parseInt()和parseFloat()不同点:
parseFloat() 所解析的字符串中第一个小数点是有效的; parseInt() 遇到小数点会停止解析,因为小数点并不是有效的数字字符。
parseFloat() 始终会忽略前导的零,十六进制格式的字符串始终会被转换成0; parseInt() 第二个参数可以设置基数,按照这个基数的进制来转换。
parseFloat() 只解析十进制,因此它没有第二个参数指定基数的用法; parseInt()方法有基模式,可以把二进制、八进制、十六进制或其他任何进制的字符串转换成整数;
Number("123AF"); //NaN
parseInt("123AF"); //123
parseFloat("123AF"); //123
Number("0xA"); //10
parseInt("0xA"); //10
parseFloat("0xA"); //0
Number(""); //0
parseInt('') // NaN
parseFloat('') // NaN
Number("Hello"); //NaN
parseInt('Hello') // NaN
parseFloat('Hello') // NaN
Number(" 1.1a"); //NaN
parseInt(' 1.1a') // 1
parseFloat(' 1.1a') // 1.1
Number(" a1.1 "); //NaN
parseInt(" a1.1 ") // NaN
parseFloat(" a1.1 ") // NaN
Number('1.1.1') // NaN
parseInt("1.1.1") // 1
parseFloat("1.1.1") // 1.1
Number("1.1"); //1
parseInt('1.1') // 1
parseFloat('1.1') // 1.1
- Number()
1) 如果字符串中只包含数字时,将其转换为十进制数值,忽略前导0
2) 如果字符串中包含有效浮点格式,如“1.1”,将其转换为对应的浮点数字,忽略前导0
3) 如果字符串中包含有效的十六进制格式,如“0xf”,将其转换为相同大小的十进制数值
4) 如果字符串为空,将其转换为0
5) 如果字符串中包含除上述格式之外的字符,则将其转换为NaN
Number("Hello world"); //NaN
Number(""); //0
Number("0000011"); //11
3. 其他类型
-
parseInt() 和 parseFloat()都返回NaN
-
Number()
1)如果是布尔值,true和false值将分别被转换为1和0。
Number(true) // 1
Number(false) // 0
2)如果是null和undefined
Number(null) // 0
Number(undefined) // NaN
3)如果是对象
调用对象的valueOf()方法,然后依照前面的规则转换返回的值。如果转换的结果是NaN,则调用对象的toString()方法,然后再依照前面的规则转换返回的字符串值。
isNaN() 和 Number.isNaN() 函数的区别?
isNaN() 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。
Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,这种方法对于 NaN 的判断更为准确。
documen.write 和 innerHTML 的区别?
document.write 的内容会代替整个文档内容,会重写整个页面,会导致页面全部重绘
innerHTML 的内容只是替代指定元素的内容,只会重写页面中的部分内容,不会导致页面全部重绘
innerHTML 与 outerHTML 的区别
对于这样一个 HTML 元素:<div>content<br/></div>
innerHTML:内部 HTML,content<br/>;
outerHTML:外部 HTML,<div>content<br/></div>;
innerText:内部文本,content ;
.call() 、.apply() 的区别
它们的作用一模一样,区别在于传入参数的形式的不同。
apply 接受两个参数,第一个参数指定了函数体内 this 对象的指向,第二个参数为一个带下标的集合,这个集合可以为数组,也可以为类数组,apply 方法把这个集合中的元素作为参数传递给被调用的函数。
call 传入的参数数量不固定,跟 apply 相同的是,第一个参数也是代表函数体内的 this 指向,从第二个参数开始往后,每个参数被依次传入函数。
Object.is() 与原来的比较操作符 “===”、“==” 的区别
使用==进行相等判断时,如果两边的类型不一致,则会进行强制类型转化后再进行比较。
使用===进行相等判断时,如果两边的类型不一致时,不会做强制类型准换,直接返回 false。
Object.is 在三等号判等的基础上特别处理了 NaN 、-0 和 +0 ,保证 -0 和 +0 不再相同,但 Object.is(NaN, NaN) 会返回 true.
Object.is 应被认为有其特殊的用途,而不能用它认为它比其它的相等对比更宽松或严格。
使用 Object.is 来进行相等判断时,一般情况下和三等号的判断相同,它处理了一些特殊的情况,比如 -0 和 +0 不再相等,两个 NaN 认定为是相等的。
escape、encodeURI、encodeURIComponent 的区别
- escape是对字符串进行编码,作用是让它们在所有电脑上可读。编码之后的效果是%XX或者%uXXXX这种形式。其中 ASCII字母、数字、
@*/+,这几个字符不会被编码,其余的都会。
注意:这个方法是针对字符串使用的,不适用于URL。
- encodeURI和encodeURIComponent都是对RUL编码,唯一区别就是编码的字符范围,其中
encodeURI方法不会对下列字符编码:
ASCII字母、数字、~!@#$&*()=:/,;?+'
encodeURIComponent方法不会对下列字符编码 :
ASCII字母、数字、~!*()'
也就是encodeURIComponent编码的范围更广,会将http://XXX中的//也编码,会导致URL不可用。
总之:
- 如果只是编码字符串,不和URL有半毛钱关系,那么用escape,而且这个方法一般不会用到。
- 如果你需要编码整个URL,然后需要使用这个URL,那么用encodeURI。
- 当你需要编码URL中的参数的时候,那么encodeURIComponent是最好方法。
var param = "中文";
console.log(escape(param)); //%u4E2D%u6587
console.log(encodeURI(param)); //%E4%B8%AD%E6%96%87
console.log(encodeURIComponent(param)); //%E4%B8%AD%E6%96%87
escape("http://www.w3school.com.cn/")
// http%3A//www.w3school.com.cn
escape("?!=()#%&")
//%3F%21%3D%28%29%23%25%26
encodeURI("http://www.w3school.com.cn/")
// http://www.w3school.com.cn/
encodeURI("http://www.w3school.com.cn/My first/")
// http://www.w3school.com.cn/My%20first/
encodeURI(",/?:@&=+$#")
//,/?:@&=+$#
对整个URL进行编码,而URL的特定标识符不会被转码。
encodeURIComponent("http://www.w3school.com.cn/")
// http%3A%2F%2Fwww.w3school.com.cn
encodeURIComponent("http://www.w3school.com.cn/p 1/")
// http%3A%2F%2Fwww.w3school.com.cn%2Fp%201%2F
encodeURIComponent(",/?:@&=+$#")
// %2C%2F%3F%3A%40%26%3D%2B%24%23
<a href="http://passport.baidu.com/?logout&aid=7&u='+encodeURIComponent("http://cang.baidu.com/bruce42")+'">退出</a>');</script>
对URL中的参数进行编码,因为参数也是一个URL,如果不编码会影响整个URL的跳转。
(Weak)Set、(Weak)Map的区别
map和forEach的区别
var array = [1,2,3,4,5];
var x = array.forEach(function(value,index){
console.log(value); //1 2 3 4 5 可遍历到所有数组元素
return value + 10
});
console.log(x); //undefined 无论怎样,总返回undefined var y = array.map(function(value,index){
console.log(value); //1 2 3 4 5 可遍历到所有数组元素
return value + 10
});
console.log(y); //[11, 12, 13, 14, 15]
forEach() 方法对数组的每个元素执行一次提供的函数。总是返回undefined;
map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。返回值是一个新的数组;
substr、substring、 slice区别
参数都是正数
- slice接收的是起始位置和结束位置(不包括结束位置)
- substring接收的是起始位置和结束位置(不包括结束位置)
- substr接收的则是起始位置和所要返回的字符串长度。
注:substring是以两个参数中较小一个作为起始位置,较大的参数作为结束位置
var test = 'hello world';
test.slice(4,7) //o w
test.substring(4,7) //o w
test.substr(4,7) //o world
test.substring(7,4) //o w
接收的参数有负数
- slice会将它字符串的长度与对应的负数相加,结果作为参数
- substring则干脆将负参数都直接转换为0
- substr则仅仅是将第一个参数与字符串长度相加后的结果作为第一个参数
var test = 'hello world';
test.slice(-3) //rld
test.substring(-3) //hello world
test.substr(-3) //rld
test.slice(3,-4) //lo w
test.substring(3,-4) //hel
test.substr(3,-4) //空字符串
offsetWidth/offsetHeight、clientWidth/clientHeight 与 scrollWidth/scrollHeight 的区别?
clientWidth/clientHeight 返回的是元素的内部宽度,它的值只包含 content + padding,如果有滚动条,不包含滚动条。
clientTop 返回的是上边框的宽度。
clientLeft 返回的左边框的宽度。
offsetWidth/offsetHeight 返回的是元素的布局宽度,它的值包含 content + padding + border 包含了滚动条。
offsetTop 返回的是当前元素相对于其 offsetParent 元素的顶部的距离。
offsetLeft 返回的是当前元素相对于其 offsetParent 元素的左部的距离。
scrollWidth/scrollHeight 返回值包含 content + padding + 溢出内容的尺寸。
scrollTop 属性返回的是一个元素的内容垂直滚动的像素数。
scrollLeft 属性返回的是元素滚动条到元素左边的距离。
URL 和 URI 的区别?
URI: Uniform Resource Identifier 指的是统一资源标识符
URL: Uniform Resource Location 指的是统一资源定位符
URN: Universal Resource Name 指的是统一资源名称
URI 指的是统一资源标识符,用唯一的标识来确定一个资源,它是一种抽象的定义,也就是说,不管使用什么方法来定义,只要能唯一的标识一个资源,就可以称为 URI。
URL 指的是统一资源定位符,URN 指的是统一资源名称。URL 和 URN 是 URI 的子集,URL 可以理解为使用地址来标识资源,URN 可以理解为使用名称来标识资源。
get 和 post 请求在缓存方面的区别
缓存一般只适用于那些不会更新服务端数据的请求。
一般 get 请求都是查找请求,不会对服务器资源数据造成修改,而 post 请求一般都会对服务器数据造成修改,所以,一般会对 get 请求进行缓存,很少会对 post 请求进行缓存。
ajax axios 和 fetch 的区别
看我的另一篇ajax 、axios、fetch的区别
defer 和 async 的区别
defer 这个属性会让脚本的加载(下载)与文档的解析同步,然后在文档解析完成后再执行这个脚本文件,这样的话就能使页面的渲染不被阻塞。多个设置了 defer 属性的脚本按规范来说最后是顺序执行的,但是在一些浏览器中可能不是这样。
比如:
<script src="file.js" defer> </script>
并行下载 file.js和其它有 defer 属性的script,执行是依照顺序执行的
async 这个属性会使脚本异步加载,不会阻塞页面的解析过程,但是当脚本加载完成后立即执行 js 脚本,这个时候如果文档没有解析完成的话同样会阻塞。多个 async 属性的脚本的执行顺序是不可预测的,一般不会按照代码的顺序依次执行。 它们将在onload 事件之前完成。
<script src="file.js" async> </script>
async属性是HTML5新增的。它将在下载后尽快执行,不能保证脚本会按顺序执行。
border:none以及border:0的区别
- 效果
边框样式无
border: none
border-style:none;
边框宽度为0px
border: 0
border-width:0;
- 性能差异
border:0;
浏览器对border-width、border-color进行渲染,占用内存。
border:none;
浏览器不进行渲染,不占用内存。
- 计算出的样式
Chrome:
border:none;
border:initial none initial;
border:0;
border:0 initial initial ;
Firefox、360:
border:none;
border:medium none;
border:0;
border:0 none;
- 浏览器兼容
- IE7-不支持border:none;
- W3C提示:请始终把border-style属性声明到border-color属性之前,元素必须在改变颜色之前获得边框。
错误说法:
-
当定义了border:none,即隐藏了边框的显示,实际就是边框宽度为0
-
当定义边框时,仅设置边框宽度也可以达到显示的效果
几个阻止行为的区别
- preventDefault() 阻止事件默认行为
- stopPropagation() W3C标准的阻止冒泡 ,作用在后续节点上,目的在执行完绑定到当前元素上的所有事件处理程序之后,停止执行所有后续节点的事件处理程序
- stopImmediatePropagation 作用在当前节点以及事件链上的所有后续节点上,目的是在执行完当前事件处理程序之后,停止当前节点以及所有后续节点的事件处理程序的运行
- cancelBubble() ie的阻止冒泡
transform 、 translate、 transition、 animation区别
- transform:应用于元素的2D或3D转换。这个属性允许你将元素旋转,缩放,移动,倾斜等;
- translate:移动,是transform的一个方法
- transition:属性是一个简写属性,用于设置四个过渡属性:
transition-property
transition-duration
transition-timing-function
transition-delay - animation 属性是一个简写属性,用于设置六个动画属性:
animation-name
animation-duration
animation-timing-function
animation-delay
animation-iteration-count
animation-direction
link和@import的区别:
- link是XHTML标签,无兼容问题;@import是在CSS2.1提出的,低版本的浏览器不支持。
- link可以加载CSS,Javascript;@import只能加载CSS。
- link加载的内容是与页面同时加载;@import需要页面网页完全载入以后加载。
- 写法不同 link的写法
<link rel="stylesheet" href="index.css">
import的写法:
<style type=”text/css”>
@import url(“index.css”);
</style>