查漏补缺(八)
css选择器权重
JS>内联样式>ID选择器>类选择器>伪类选择器=属性选择器>伪元素选择器>通用选择器
伪元素和伪类元素的区别
- 伪类是在已有DOM标签的基础上,根据不同状态产生对应的样式,状态根据用户行为动态变化;伪元素则是在一个不存在的DOM上为其添加样式;
- 伪类元素使用冒号(:),伪元素使用双冒号(::);
- animation-timing-function:linear、ease、jump、step
- cellIndex是td标签的属性
- join()把一个数组转换成字符串,如果括号里没有值,默认以逗号分隔
- reduce()是一个累加器:求数组值的和、求数组最大值、数组去重
参考文章:https://www.cnblogs.com/amujoe/p/11376940.html
['a','b','c'].join() //'a,b,c'
['a','b','c']+'' //'a,b,c'
['a','b','c'].reduce((a,b)=>a+b,'') //'abc'
['a','b','c'].join('') //'abc'
- 数组与字符串相加,转换成各自的字符串再加
- +'3’是number类型
- new Number是一个内置的函数构造函数。 虽然它看起来像一个数字,但它并不是一个真正的数字:它有一堆额外的功能,是一个对象。
译者注:==会引发隐式类型转换,右侧的对象类型会自动拆箱为Number类型。
然而,当我们使用===操作符时,类型和值都需要相等,new Number不是一个数字,是一个对象类型。两者都返回 false。
TCP协议通过使用连续ARQ协议和滑动窗口协议,来保证数据传输的正确性,从而提供可靠的传输
箭头函数没有自己的this,arguments,super或new.target
脚本
放中的情况:脚本会优先加载,但加载过程中,还没加载完,会使脚本访问不到中的元素。
放底部:脚本在加载后加载,能够保证脚本有效地访问的元素。
例外情况:脚本中没有访问元素的情况下,两种加载方式效果一致。
http请求返回码
使用Promise封装Ajax操作
return new Promise(function(resolve, reject){
var req = new XMLHttpRequest();
req.open("POST", "www.baidu.com", true);
req.onload = function(){
if(req.readyState === 4 && req.status === 200){
resolve(req.response);
} else {
reject(req.statusText);
}
}
req.onerror = function(){
reject(Error("网络异常"));
}
});
indexOf检索数组
let arr = ['hello', 'world']
arr.indexOf('world') //1
indexOf 方法使用严格的相等性(‘===’)搜索数组。如果值的类型不同(例如4和’4’),返回-1。
参考文章:https://baijiahao.baidu.com/s?id=1672723669095917700&wfr=spider&for=pc
Array.prototype.slice原理
slice是Array这个类里的一个方法,所以使用时为Array.prototype.slice。而slice是数组或字符串截取方法,因此可以截取类数组里的值。
let arr = [
{index: 0},{index: 1},
{index: 2},{index: 3}
]
console.log(arr.slice(0,2)) //[{index: 0},{index: 1}]
let obj = {0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4}
Array.prototype.slice(obj) //['a','b','c','d']
Array.prototype.slice(obj, 0, 2) //['a','b']
prototype和__proto__
- 函数和原型对象:每个函数都有一个默认的prototype属性,这个属性默认指向一个Object空对象(也可叫做原型对象),原型对象里有一个constructor属性,它指向函数对象。因此,函数对象和它的原型对象是相互引用
function Fun(){}
console.log(Fun.prototype)
console.log(Fun.prototype.constructor === Fun) //true
//给函数对象的原型对象上添加方法,实例进行调用
Fun.prototype.add = function(){}
- 函数和实例对象:函数有一个默认的prototype属性,叫做显式原型,实例对象有一个__proto__属性,叫做隐式原型。实例对象的隐式原型等于其构造函数的显式原型
function Fun(){}
let fun = new Fun()
console.log(fun.__proto__ === Fun.prototype) //true
- 构造函数的prototype属性在定义构造函数时添加,实例对象的__proto__属性在创建实例对象时添加
Math.max()和Math.min()无参数时
Math.min() //Infinity
Math.max() //-Infinity
console.log(Math.min(1,3,'e')) //NaN,如果有任意一个参数无法转为数值,返回NaN
Object.create()
创建一个对象,这个对象的原型对象为这个方法的第一个参数,第二个参数如果不为undefined,则为自身对象的属性
let obj = { name: 'xxx' }
let o = Object.create(obj, {
age: {
value: 12,
writeable: true,
configurable: true,
enumerable: true
}
}) //实例o的原型对象为obj
o.name //'xxx',此时对象o本身并没有name属性,打印出来的是原型对象上的name
console.log(o) //{ age: 12 }
//防止Object构造函数的原型被修改时对新建的对象产生影响
Object.create(null)
delete
- delete使用原则:delete 操作符用来删除一个对象的属性。
- delete在删除一个不可配置的属性时在严格模式和非严格模式下的区别:
(1)在严格模式中,如果属性是一个不可配置(non-configurable)属性,删除时会抛出异常;
(2)非严格模式下返回 false。 - delete能删除隐式声明的全局变量:这个全局变量其实是global对象(window)的属性
- delete能删除的:
(1)可配置对象的属性(2)隐式声明的全局变量 (3)用户定义的属性 (4)在ECMAScript 6中,通过 const 或 let 声明指定的 “temporal dead zone” (TDZ) 对 delete 操作符也会起作用
delete不能删除的:
(2)显式声明的全局变量 (2)内置对象的内置属性 (3)一个对象从原型继承而来的属性 - delete删除数组元素:
(1)当你删除一个数组元素时,数组的 length 属性并不会变小,数组元素变成undefined
(2)当用 delete 操作符删除一个数组元素时,被删除的元素已经完全不属于该数组。
(3)如果你想让一个数组元素的值变为 undefined 而不是删除它,可以使用 undefined 给其赋值而不是使用 delete 操作符。此时数组元素是在数组中的 - delete 操作符与直接释放内存(只能通过解除引用来间接释放)没有关系。
JS运行顺序
JS解析执行时,会分为同步任务和异步任务,异步任务又分为宏任务和微任务。同步任务先执行,执行到异步任务时会将异步内容放入任务队列里,把同步任务执行完之后,开始执行任务队列里的内容,执行任务队列时,先执行微任务再执行宏任务。
同步任务:Promise
宏任务:setTimeout、setInterval、setImmediate
微任务:process.nextTick(tick比then先执行)、Promise.then
内存泄漏
内存泄漏就是所写的变量、对象等代码没使用但是一直占用着内存。
内存泄漏的几个原因:
(1)定义了一个在其他任何地方不会使用的数据
function fun(){
str = 'xxxxxxxxxxx'
}
(2)定时器
let data = [{ name: 'xxx' }, { name: 'yyy' }];
setInterval(function() {
var node = document.getElementById('Node');
if(node) {
// 处理 node 和 someResource
node.innerHTML = JSON.stringify(data));
}
}, 1000);
如果id为 Node 的元素从DOM中移除,该定时器仍会存在,同时,因为回调函数中包含对data的引用,定时器外面的data也不会被释放
(3)闭包
(4)没有清理对DOM元素的引用
const refA = document.getElementById('refA')
document.body.removeChild(refA) // dom删除了
console.log(refA, 'refA') // 但是还存在引用能console出整个div 没有被回收
refA = null
console.log(refA, 'refA') // 解除引用
参考文章:https://blog.csdn.net/kun_ding_bei/article/details/127987542
判断是否为空对象
function isObject(obj){
return (
obj == null || obj == undefined ||
(typeof obj == 'object' && Object.keys(obj).length == 0)
)
}