CSS隐藏元素的几种方法(至少说出三种)
Opacity:元素本身依然占据它自己的位置并对网页的布局起作用。它也将响应用户交互;
Visibility:与 opacity 唯一不同的是它不会响应任何用户交互。此外,元素在读屏软件中也会被隐藏;
Display:display 设为 none 任何对该元素直接打用户交互操作都不可能生效。此外,读屏软件也不会读到元素的内容。这种方式产生的效果就像元素完全不存在;
Position:不会影响布局,能让元素保持可以操作;
z-index:-999
数组的方法
/*
concat() 连接两个或更多的数组,并返回结果。
join() 把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。
pop() 删除并返回数组的最后一个元素
push() 向数组的末尾添加一个或更多元素,并返回新的长度。
reverse() 颠倒数组中元素的顺序。
shift() 删除并返回数组的第一个元素
slice() 从某个已有的数组返回选定的元素
sort() 对数组的元素进行排序
splice() 删除元素,并向数组添加新元素。
toSource() 返回该对象的源代码。
toString() 把数组转换为字符串,并返回结果。
toLocaleString() 把数组转换为本地数组,并返回结果。
unshift() 向数组的开头添加一个或更多元素,并返回新的长度。
valueOf() 返回数组对象的原始值。
*/
//修改原数组 splice pop unshift push reverse sort
//不修改原数组(返回一个新的数组) slice concat join
// var list = [1, 2, 3];
// list.pop();
//删除数组的最后一个元素 [1,2];
// list.unshift(0,1);
// 头部添加 [0,1,1,2,3];
// list.push(4,5);
//尾部添加 [1,2,3,4,5]
// var arr = list.concat(4,[{a:1},6]);//把两个数组连接起来
// let arr = list.join("-");
// let arr = list.reverse(); //颠倒顺序
//slice是返回一个子数组
// let arr = list.slice(2);//如果 end 未被规定,那么 slice() 方法会选取从 start 到数组结尾的所有元素。
// let arr = list.slice(1,2); //slice(start,end)
//list.slice(1,-2);//设置了两个参数,终止下标为负数,当出现负数时,将负数加上数组长度的值来替换该位置的数。
//splice是在原数组的基础上进行修改 数组是引用型 所以需要注意是只要引用了该数组就会随着splice改变而改变全部引用了该数组的数组。
//删除 2个参数
// var arr = list.splice(0,1); ==>[2,3]
// 可以删除任意数量的项,只需指定2个参数;splice(需要删除的数组的下标,删除的数量)
//插入 需要3个参数
// var list = [1,2,4,6,3];
// list.splice(2,0,4,5); //==>[1,2,4,5,4,6,3]
//可以向指定位置插入任意数量的项,需要3个参数, 起始位置 、0(要删除的项数) 、要插入的任意数量的项。
//例如 splice( 2 , 0 , 4,6 );
//可以这么理解 需要插到2的位置 那么原本2的位置就需要变到3的位置
//替换,
//可以向指定位置插入任意数量的项,同时删除任意数量的项,需要3个参数,起始位置、要删除的项数、要插入的任意数量的项。
//例如splice(2,1,4,6); 会从位置 2 开始插入4和6。
// list.splice(2,1,4,6); //==>[1, 2, 4, 6, 6, 3]
//sort是排顺序的 需要一个函数
//按照第一个数字大小进行排序;
// function compare(a, b) {
// return a - b;//正序;
// return b - a;//倒序;
// }
// list.sort(compare);
// console.log(list)
call apply bind 三者的区别与作用
//call apply bind 三者的区别与作用
//这三个函数就是用来改变this的指向的
/*
a.一般函数,this指向全局对象window;
b.在严格模式下"use strict",为undefined.
c.对象的方法里调用,this指向调用该方法的对象. 【this指的是,调用函数的那个对象】
d.构造函数里的this,指向创建出来的实例.
call,apply,bind,改变函数运行时的指向,当第一个参数为null或undefind时,指向window
call:传入参数列表,改变函数指向并立即调用,第一个参数同apply,第二个参数必须是单个参数列表,不能是数组
apply:可以传入数组,第一个参数:要绑定给this的值 第二个参数:参数列表(可以是数组)
bind:改变this指向后,返回的是函数
*/
function fun() {
let name = 'jisoo'
console.log(this.name) //原本this是指向fun这个函数的
}
let bps = {
name: 'blinks'
}
fun.call(bps) //现在这个this是指向bp这个对象
//可以这么理解 把bps的全部属性拷到fun里面了
let jisoo = {
name: 'jisoo',
h(v) {
console.log(v)
},
t(){
console.log(this.name)
}
}
let bp = {
name: 'blinks'
}
jisoo.h('hello')
jisoo.h.call(bp,bp.name)
jisoo.h.apply(bp,[bp.name]) // 与call的区别就是参数需要用数组包着
let newCallBackFun = jisoo.h.bind(bp,bp.name) //返回的是一个fun
newCallBackFun()
jisoo.t.call(bp)
//继承
function blackpink() {
this.name = function () {
console.log('blackpink')
}
}
function Lisa() {
this.solo = function () {
console.log('lalisa')
}
}
function Jisoo() {
blackpink.call(this)
Lisa.call(this)
}
let jisoo = new Jisoo()
jisoo.name()
jisoo.solo()
http常用状态码
100 Continue 继续,一般在发送post请求时,已发送了http header之后服务端将返回此信息,表示确认,之后发送具体参数信息
200 OK 正常返回信息
201 Created 请求成功并且服务器创建了新的资源
202 Accepted 服务器已接受请求,但尚未处理
301 Moved Permanently 请求的网页已永久移动到新位置。
302 Found 临时性重定向。
303 See Other 临时性重定向,且总是使用 GET 请求新的 URI。
304 Not Modified 自从上次请求后,请求的网页未修改过。
400 Bad Request 服务器无法理解请求的格式,客户端不应当尝试再次使用相同的内容发起请求。
401 Unauthorized 请求未授权。
403 Forbidden 禁止访问。
404 Not Found 找不到如何与 URI 相匹配的资源。
500 Internal Server Error 最常见的服务器端错误。
503 Service Unavailable 服务器端暂时无法处理请求(可能是过载或维护)。
怎么让Chrome支持小于12px 的文字
针对谷歌浏览器内核,加webkit前缀,用transform:scale()这个属性进行缩放!
span{
font-size: 10px; //为了一些可以12px一下的网站
-webkit-transform: scale(0.5);
display: inline-block; //transform需要块级元素
}
运算符
1.<< 24<<1 把1向左移动24位 1 => 1 0000 0000 0000 0000 0000 0000 十进制就是 :16777216
2.>> 同理
~~ 取整 、将Boolean转成1和0
(~~(Math.random()*(1<<24))).toString(16)
~~1.2 ==>1
~~ -1.2 ==>-1
~~true===1 ==> true
~~false===0 ==> true
~ 单波浪符号 加1取反
~-1 ⇒ 0
~-2 ⇒ 1
~2 ⇒ -3
toString(16) 转16进制
Math.min() => 没有传入值的时候是返回无穷大 Infinity
Math.max() => 无穷小 -Infinity
js运行机制
JavaScript 单线程,任务需要排队执行
同步任务进入主线程排队,异步任务进入事件队列排队等待被推入主线程执行
定时器的延迟时间为 0 并不是立刻执行,只是代表相比于其他定时器更早的被执行
以宏任务和微任务进一步理解js执行机制
整段代码作为宏任务开始执行,执行过程中宏任务和微任务进入相应的队列中
整段代码执行结束,看微任务队列中是否有任务等待执行,如果有则执行所有的微任务,直到微任务队列中的任务执行完毕,如果没有则继续执行新的宏任务
执行新的宏任务,凡是在执行宏任务过程中遇到微任务都将其推入微任务队列中执行
反复如此直到所有任务全部执行完毕
console.log(1.)
setTimeout(() => {
console.log(2.)
setTimeout(() => {
console.log(3.)
}, 1000);
console.log(5.)
}, 1000);
console.log(4.)
结果 1 4 2 5 3
数据类型(也考察存的是堆还是栈)
(基本类型):String、Number、Boolean、Null、Undefined、Symbol。
引用数据类型:Object、Array、Function。
基本类型的数据是存放在栈内存中的,而引用类型的数据是存放在堆内存中的
ES6 引入了一种新的原始数据类型 Symbol ,表示独一无二的值,最大的用法是用来定义对象的唯一属性名。
或者常量
let sy = Symbol("key1");
// 写法1
let syObject = {};
syObject[sy] = "kk";
console.log(syObject); // {Symbol(key1): "kk"}
const COLOR_RED = Symbol("red");
const COLOR_YELLOW = Symbol("yellow");
const COLOR_BLUE = Symbol("blue");
function getConstantName(color) {
switch (color) {
case COLOR_RED :
return "COLOR_RED";
break;
case COLOR_YELLOW :
return "COLOR_YELLOW ";
break;
case COLOR_BLUE:
return "COLOR_BLUE";
break;
default:
return ("Can't find this color");
break;
}
}
var color = COLOR_RED;
var colorName = getConstantName(color);
console.log(colorName)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4MirmH7W-1631797777000)(C:\Users\lovelife_xu\AppData\Roaming\Typora\typora-user-images\image-20210905215200319.png)]
js原型链
/*
js的 prototype 与 __proto__
prototype : 原型
__proto__ : 原型链(连接点)
从属关系
prototype -> 函数的一个属性 也就是一个对象{} 但是这个对象有一些规定好的属性就在里面了
__proto__ -> 对象Object的一个属性 也就是一个对象{}
对象的__proto__保存着该对象的构造函数的prototype
*/
//这是一个构造函数
function T() {
this.a = 1;
}
//使用prototype给Object的prototype绑定了b属性
Object.prototype.b = 2
//使用prototype给T的prototype绑定了c属性
T.prototype.c = 3
console.log(T.prototype) //构造函数有prototype
console.log(T.__proto__) //ƒ () { [native code] }
console.log(T.__proto__ === Function.prototype) // true
console.log(T.__proto__ === Object.prototype) // false
console.log(T.__proto__ === Object.__proto__) // true
console.log(T.prototype.__proto__ === Object.prototype) //指向Object的prototype true
console.log(Object.prototype)//这里的Object的原型对象
//实例对象
let t = new T()
console.log(t) //t对象
console.log(t.__proto__) //T构造函数的prototype
console.log(t.__proto__.__proto__) //Object的prototype
console.log(t.prototype) //实例对象没有prototype
console.log(t.__proto__ === T.prototype) //t的__proto__保存着该对象的构造函数的prototype(T的prototype)
console.log(T.prototype.__proto__ === Object.prototype)
/*
t{
a : 1
__proto__:T.prototype{
c:3
__proto__:Object.prototype{
b:2
x __proto__ 、没有 __proto__ 、__proto__ == null
}
}
}
*/
console.log(t.a)
console.log(t.b)
console.log(t.c)
// const T = new Function()
// T函数也是new Function 出来的,那么Function也是一个函数,那么函数就会有prototype和__proto__,他们都是一个函数,至于怎么实现就不给看。Function.prototype已经是最底层了,Function.__proto__指向的就是Function.prototype,所以他们全等 这都是底层已经规定好的了。
console.log(Function) // ƒ Function() { [native code] }
console.log(Function.prototype) // ƒ () { [native code] }
console.log(Function.__proto__) // ƒ () { [native code] }
//Function.__proto__指向的就是Function.prototype
console.log(Function.__proto__ === Function.prototype) // true
// const obj = {} 这是怎么来的? 那就是通过new Object()出来的
// const obj = new Object(); 那么这个Object()也是一个function(函数)
// 那么new Function就会指向function的prototype
console.log(typeof Object) // function
console.log(Object) // ƒ Object() { [native code] }
console.log(Object.__proto__) // ƒ () { [native code] }
console.log(Object.__proto__ === Function.prototype) //true //因为Object也是一个函数,Object的__proto__就会指向Function的prototype
console.log(Function.__proto__ === Function.prototype) // true
console.log(Object.__proto__ === Function.prototype) // true
// => 得出Function.__proto__ === Object.__proto__
console.log(Function.__proto__ === Object.__proto__) // true
console.log(Object.prototype.__proto__)// null //这就是原型链的顶端
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R6sHjEyM-1631797777002)(C:\Users\lovelife_xu\Desktop\js知识点总结\js原型链.png)]
为什么要用prototype
function NewObj(name,num){
this.name = name;
this.num = num;
this.changNum = function(c){
this.num = c;
}
}
const obj1 = new NewObj('aloha',10)
obj1 = {
name:'aloha';
num:10;
changeNum :function(c){
this.num = c
}
obj1.changNum(100);
obj1.num; // 结果是100
//如果我们现在想要改变changeNum函数呢?
//变成 ==> this.changNum = function(c){
// this.num = c*2;
// }
//那么你会这样做,想要修改这个changeNum函数就需要修改这个NewObj这个构造函数
function NewObj(name,num){
this.name = name;
this.num = num;
this.changNum = function(c){
this.num = c*2;
}
}
//然后再调用这个修改后的方法
obj1.changNum(100);
obj1.num; //依然是100,也就是说这个对象并不受我们修改的模板影响到
//这是为什么呢?
//原因是通过构造函数模板new出来的instance(实例)是直接copy构造函数本身自己一份赋值给刚new出来的instance,所以这个instance是完全在一个独立的内存中,而不是引用(指向)构造函数的内存的。
//所以如果你使用修改构造函数的changeNum函数模板的这个方法,你就需要这样做才能看到修改changeNum函数后的NewObj正确的结果。
// 你需要再new一个新的实例出来 obj2
const obj2 = new NewObj('aloha',10)
obj2 = {
name:'aloha';
num:10;
changeNum :function(c){
this.num = c*2
}
//这个obj2与上面的obj1是不一样的
//obj1 = {
// name:'aloha';
// num:10;
// changeNum :function(c){
// this.num = c
// }
//这个时候你再调用ChangeNum(100)
obj2.changNum(100);
obj2.num; // 结果是200
//而构造函数这种形式每次都会把自身的属性全部copy一份给每个instance,这就造成了不必要的浪费;并且,当我们想修改这个方法时,就必须重新生成所有的instance才能获得更新
//怎么解决这个问题呢?有一个原型对象。原型对象里的属性和方法并不是像构造函数自身属性一样copy给每个instance,而是“引用”,也可以理解为给每个instance提供一个指向该原型对象的指针,这样每个instance就能找到原型对象里的属性,而很明显,这是一种共享,也就是说,当你修改了这个原型里的属性,那么所有共享该属性的instance都能获得这个修改。因此,原型恰好解决了上面提到的两个问题。
function NewObj(name,num){
this.name = name;
this.num = num;
}
NewObj.prototype.changNum = function(c){
this.num = c;
}
var newObj1 = new NewObj("kemi",10);
newObj1.changNum(100);
newObj1.num; //很明显是100
NewObj.prototype.changNum = function(c){
this.num = c*2;
}//我们重新修改一下这个方法
newObj1.changNum(100);
newObj1.num; //变成200了。
//为什么一般情况下会把属性直接写在构造函数内,而方法通过prototype添加呢?这两种方式的区别上面其实已经有所展现了:大部分的instance的属性都是不同的,比如说name,因此在构造函数内通过this直接绑定给instance无疑是个好方案,而方法通常是通用的,使用prototype可以让每个instance共享同一个方法,而不用每个都copy一次,又能实现实时更新。
浅拷贝和深拷贝
基本数据类型:名字和值都存在栈中
引用数据类型:名字在栈中,值在堆中,栈内存会提供一个引用地址,指向堆内存中的值
浅拷贝:1.for只遍历第一层 2.assign 3. =直接赋值
深拷贝:1.递归遍历所有层级 2.利用JSON对象【JSON.stringfy() JSON.parse()】 3.通过jQuery的extend方法实现深拷贝 4.lodash函数库实现深拷贝 5.用slice实现对数组的深拷贝,slice() 方法可从已有的数组中返回选定的元素。6.使用扩展运算符实现深拷贝 8.Reflect法 9.用concat实现对数组的深拷贝 10.直接使用var newObj = Object.create(oldObj),可以达到深拷贝的效果。11.手动实现深拷贝 7.如对象的value是基本类型,可以用Object.assign来实现深拷贝,但是要把它赋值给一个空对象
assign第一层是深拷贝,第二层以后是浅拷贝
对于浅拷贝来说,对于一个数组(数组是一个对象),只要我们修改了一个拷贝数组,原数组也会跟着改变。
因为他们引用的是同一个地址的数据,拷贝的时候并没有给b数组创造独立的内存,只是把a数组指向数据的指针拷贝给了b;
而深拷贝就与其相反,将会给b数组创造独立的内存,并且将a数组的内容一一拷贝进来,两者互不影响。
ES6语法中也给我们提供了一个浅拷贝的方法`Object.assign(target, sources)`
深拷贝的话一共有两种方式: `递归拷贝` 和 `利用JSON函数深拷贝`JSON.parse(JSON.stringify(a))
事件委托 冒泡机制
冒泡机制
气泡从水底开始往上升,由深到浅,升到最上面。
这个气泡就相当于我们这里的事件,而水则相当于我们的整个dom树;事件从dom 树的底层 层层往上传递,直至传递到dom的根节点。
.a{
width: 300px;
height: 300px;
background-color: black;
color: white;
}
.b{
width: 200px;
height: 200px;
background-color: green;
}
.c{
width: 100px;
height: 100px;
background-color: red;
}
<div class="a">
a
<div class="b">
b
<div class="c">
c
</div>
</div>
</div>
document.getElementsByClassName('a')[0].addEventListener('click',()=>{console.log('click A')})
//点击c区域 控制台返回 clikc A
//点击b区域 控制台返回 clikc A
//点击a区域 控制台返回 clikc A
给b添加一个点击fun
document.getElementsByClassName('b')[0].addEventListener('click',()=>{console.log('click B')})
//点击c区域 控制台返回 clikc A clikc B
//点击b区域 控制台返回 clikc A clikc B
//点击a区域 控制台返回 clikc A
终止事件的冒泡
1.event.stopPropagation() 这种方法相当于把泡泡戳破 那么就不会继续向上传递
document.getElementsByClassName('a')[0].addEventListener('click', (event) => {
console.log('click A')
})
document.getElementsByClassName('b')[0].addEventListener('click', (event) => {
console.log('click B')
event.stopPropagation()
})
//点击c区域 控制台返回 clikc B
//点击b区域 控制台返回 clikc B
//点击a区域 控制台返回 clikc A
2.判断 过滤
这是通过判断是不是点击了当前函数绑定的节点 (绑定在子节点上)
document.getElementsByClassName('a')[0].addEventListener('click', (event) => {
if (event.target == event.currentTarget) {
console.log('click A')
}
})
document.getElementsByClassName('b')[0].addEventListener('click', (event) => {
if (event.target == event.currentTarget) {
console.log('click B')
}
})
document.getElementsByClassName('c')[0].addEventListener('click', (event) => {
if (event.target == event.currentTarget) {
console.log('click C')
}
})
//这个是直接把判断函数绑定在父节点上 全部操作都交给父节点完成
//这就是事件委托
document.getElementsByClassName('a')[0].addEventListener('click', (event) => {
let target = event.target;
switch (target.className) {
case "a":
console.log("您好,我是a");
break;
case "b":
console.log("您好,我是b");
break;
case "c":
console.log("您好,我是c");
break;
}
})
总结:方法一在于取消事件冒泡,即当某些节点取消冒泡后,事件不会再传递;方法二在于不阻止冒泡,过滤需要处理的事件,事件处理后还会继续传递;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-79aF16gC-1631797777003)(C:\Users\lovelife_xu\Desktop\js知识点总结\20140418093749984.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fNn9qhS2-1631797777005)(C:\Users\lovelife_xu\Desktop\js知识点总结\25e22373497bb4709df386a229f217a.png)]
instanceof、typeof、Object.prototype.toString.call()的用法和区别
- instanceof是用来判断一个实例对象的原型链中是否存在构造函数的prototype
语法:obj instanceof prototype
//instanceof 运算符用来判断 constructor.prototype 是否存在object的原型链上。
function A(){};
function B(){};
var a = new A();
a instanceof A; //true
a instanceof B; //false
- typeof
语法:typeof variable 或 typeof(variable)
Undefined "undefined"
Null "object"
Boolean "boolean"
Number "number"
String "string"
Symbol (ECMAScript 6 新增) "symbol"
宿主对象(由JS环境提供) Implementation-dependent
函数对象([[Call]]) "function"
任何其他对象 "object"
※ typeof 无法判断 array。
※ typeof 无法判断 Set 、 Map。 => 使用 obj instanceof Set / Map 判断
-
Object.prototype.toString.call()
function A(){}; var a = new A() Object.prototype.toString.call(a) //result:"[object Object]" Object.prototype.toString.call(A) //result:"[object Function]" Object.prototype.toString.call(1) //result:"[object Number]" Object.prototype.toString.call('a') //result:"[object String]" Object.prototype.toString.call() //result:"[object Undefined]" Object.prototype.toString.call(null) //'[object Null]' var b = [1,2,3] Object.prototype.toString.call(b) //result:"[object Array]" 使用object.prototype.toString 对象内置的toString方法 在使用时使用call或者apply调用即可 他可以判断全部数据类型 null undefiend 这些也可以
0.1 + 0.2 === 0.3? 不等于
要弄清这个问题的原因,首先我们需要了解下在计算机中数字是如何存储和运算的。在计算机中,数字无论是定点数还是浮点数都是以多位二进制的方式进行存储的。
对于整数来说,十进制的35会被存储为: 00100011 其代表 2^5 + 2^1 + 2^0。
对于纯小数来说,十进制的0.375会被存储为: 0.011 其代表 1/2^2 + 1/2^3 = 1/4 + 1/8 = 0.375
而对于像0.1这样的数值用二进制表示你就会发现无法整除,最后算下来会是 0.000110011....由于存储空间有限,最后计算机会舍弃后面的数值,所以我们最后就只能得到一个近似值。
另外说一句,除了那些能表示成 x/2^n 的数可以被精确表示以外,其余小数都是以近似值得方式存在的。
解决办法:
//其实ES6 已经在Number对象上面,新增一个极小的常量Number.EPSILON。根据规格,它表示 1 与大于 1 的最小浮点数之间的差。Number.EPSILON实际上是 JavaScript 能够表示的最小精度。误差如果小于这个值,就可以认为已经没有意义了,即不存在误差了。
Number.EPSILON=(function(){ //解决兼容性问题
return Number.EPSILON?Number.EPSILON:Math.pow(2,-52);
})();
//上面是一个自调用函数,当JS文件刚加载到内存中,就会去判断并返回一个结果,相比if(!Number.EPSILON){
// Number.EPSILON=Math.pow(2,-52);
//}这种代码更节约性能,也更美观。
function numbersequal(a,b){
return Math.abs(a-b)<Number.EPSILON;
}
//接下来再判断
var a=0.1+0.2, b=0.3;
console.log(numbersequal(a,b)); //这里就为true了
箭头函数this
箭头函数的this
跟常规函数的规则完全不同。无论用什么方式、在哪里调用箭头函数,里面的this
永远是外层函数的this
。也就是说,箭头函数的this
是由词法决定的,它没有定义自己的执行上下文。
let obj = {
myFunc(items){
console.log(this)
let callback = ()=>{
console.log(this);
};
items.forEach(callback)
}
}
obj.myFunc([1,2,3])
//{myFunc: ƒ}
//{myFunc: ƒ}
//{myFunc: ƒ}
//{myFunc: ƒ}
在上面的代码中,myFunc()就是箭头函数callback()的外层函数,箭头函数里的this等于外层函数的this,也就是myFunc()
综上所述,由词法决定this的指向,是箭头函数非常使用的特性之一。在方法里使用回调函数就很方便,this指向很明确,不用去写替换this和绑定this的方法了。
Js数组去重
-
new Set(arr)
-
for嵌套,两层循环,如果第二个等于第一个,删掉第二个,用splice方法
splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目。
注释:该方法会改变原始数组。 -
indexOf :建一个空数组,循环目标数组,判断新数组中是否有当前单参数,没有就push,有就跳过
-
includes:查找数组中是否有某个元素
z-index
z-index 属性设置元素的堆叠顺序。拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面。
Z-index 仅能在定位元素上奏效(例如 position:absolute;)
需要在同一级标签
<style>
.box1 {
width: 100px;
height: 100px;
background-color: black;
}
.box2 {
position: absolute;
width: 100px;
height: 100px;
background-color: rgb(153, 1, 1);
z-index: 99;
}
.box3 {
position: absolute;
width: 100px;
height: 100px;
background-color: rgb(38, 161, 209);
z-index: 999;
}
</style>
<body>
<div class="box1">
<div class="box2"></div>
<div class="box3"></div>
</div>
</body>
显示转换 与 隐式转换
转换成number类型
+'1' ⇒ 1
+undefined ⇒ NaN
转换成string类型
1 + '' ⇒ '1'
转换成boolean类型
!0 ⇒ true
!false ⇒ true
!'' ⇒ true
!'1' ⇒ false
!!undefined ⇒ false
!!null ⇒ false
!!NaN ⇒ false
!!双感叹号转换undefined null NaN 这些特殊的数据类型
遍历方法
遍历对象时推荐使用for…in,其中item为对象的key。使用for…of会报错。
遍历数组时推荐使用for…of,其中item为数组每一项的值。使用for…in则不能保证遍历顺序且会遍历出自定义属性。
for…in是ES5特性,for…of是ES6特性,因此需要注意兼容性。
如果要使用for…of遍历普通对象,需要配合Object.keys()一起使用
防抖
const debounce = (func,wait) => {
//定义一个timer计时器
let timer = null
//返回时间计时器
return function(){
//判断
if(timer) timer.clearTimeout()
timer = setTimeout(()=>{
func.apply(this,arguments)
timer = null
})
}
}
迭代器
迭代器可以理解为for of循环,又叫遍历器
在js里原生具备 Iterator 接口的数据结构如下:
Array
Map
Set
String
TypedArray
函数的 arguments 对象
NodeList 对象
这些类型就可以直接使用for of循环了。
比如对象里面就没有Iterator 接口 那么就不可以直接使用for of 。