八股(自己整理)JS篇2

53 阅读8分钟

1.事件绑定

允许监听DOM元素上的各种事件(如点击、滚动、键盘输入等)并执行相应的代码

三种绑定方式:
a.HTML内联事件处理程序

不利于维护;可能导致全局变量污染

<button onclick="handleClick()">点击我</button>

<script>
  function handleClick() {
    console.log('按钮被点击');
  }
</script>

b.DOM0级事件处理程序

通过JS直接赋值给元素的事件属性

每个事件只能绑定一个处理程序

<button id="btn">点击我</button>

<script>
  const btn = document.getElementById('btn');
  btn.onclick = function() {
    console.log('按钮被点击');
  };
  // 可覆盖之前的事件处理程序
  btn.onclick = function() {
    console.log('新的点击处理');
  };
</script>
c.DOM2级事件处理程序

支持多个处理程序、事件捕获/冒泡控制、更灵活的事件管理

<button id="btn">点击我</button>

<script>
  const btn = document.getElementById('btn');
  // 绑定事件
  btn.addEventListener('click', function() {
    console.log('按钮被点击');
  });
  // 可绑定多个处理程序
  btn.addEventListener('click', function() {
    console.log('另一个处理程序');
  });
  // 解绑事件(需使用相同的函数引用)
  const handler = () => console.log('可移除的处理程序');
  btn.addEventListener('click', handler);
  btn.removeEventListener('click', handler); // 成功移除
</script>
事件冒泡与捕获

事件在DOM树中传播有两种机制:

a.事件冒泡(默认)

事件从触发元素开始逐级向上传播到父元素

b.事件捕获

事件从文档根节点开始,逐级向下传播到触发元素

阻止事件冒泡:
a.event.stopPropagation()

最常用

element.addEventListener('click', function(event) {
  event.stopPropagation(); // 阻止事件继续冒泡
  console.log('事件被捕获,但不会向上传播');
});
b.内联事件使用return false

同时阻止冒泡和默认行为

c.window.event.cancelBubble=true

2.promise

解决回调地狱的问题 有三种状态: pending fulfilled(成功) rejected(失败) 状态改变只能从pending到另外两种 且不能再改变 对象的实例化方法: then catch finally then: 指定用于得到成功value的成功回调和失败回调,返回新的promise实例化对象 成功的状态:执行then的第一个回调函数 失败的状态:执行then方法的第二个回调函数 then方法的返回值的promise实例化对象的状态取决于回调函数中的内容 返回非promise实例化对象,得到成功的promise 抛出异常,得到失败的promise 返回promise实例化对象,则该对象的状态和结果值影响result常量的结果值

const p1=new Promise( (resolve,reject)=>{
    resolve('ok');
})
const result=p1.then(value=>{
      return value;   //状态fulfilled 结果value
      return new Promise((resolve,reject)=>{
             reject('error')   //状态rejected 结果error
             resolve('ok')     //状态fulfilled 结果ok
      })  
      throw'异常信息'     //状态rejected 结果异常信息 
},reason =>{
      console.log(reason);
})

链式调用 then的执行依赖上一步结果 all方法: 针对于多个promise的异步任务的处理 接受一个数组类型的参数,数组里放的是多个promise实例化对象 返回值:promise对象,状态由数组里的所有promise决定 所有promise都成功,结果成功,结果值由每一个promise的结果值组成 只要有一个失败的就失败,结果值是失败的这个promise的结果

3.深拷贝浅拷贝

浅拷贝:

将原对象或数组的值复制到一个新的对象或数组中,

但新的对象或数组的元素或属性依然是原对象或数组的引用

常见的浅拷贝方法:

①Object.create(obj)

创建一个新对象,并将原对象作为新对象的原型

新对象可以访问原对象的所有属性和方法

const obj2=Object.create(obj1);

②Object.assign({},obj)

用于将一个或多个源对象的属性复制到目标对象中

let a={
      name:'A',
      like:{n:'coding'}
}
let b=Object.assign({},a);
a.name='B';
a.like.n='running';
console.log(b.name); //A
console.log(b.like.n); //running

原始类型不会跟着a修改,引用类型会

③[].concat(arr)

用于将一个或多个数组合并成一个新数组

修改时同上

④[...arr]数组解构

同上

⑤arr.slice()

从数组中提取指定区间的元素创建一个新的数组

接受两个参数:开始索引和结束索引

深拷贝:

将原对象或数组的值复制到一个新的对象或数组中,

新的对象或数组的属性或元素完全独立于原对象或数组,不共享引用地址

常见的深拷贝方法:

JSON.parse(JSON.stringify(obj))

JSON.stringify将js对象或值转换为JSON字符串

JSON.parse将JSON字符串解析为对应的js对象或值

手写深拷贝
function deepCopy(obj){ 
    //不是引用类型就不拷贝
    if(!(obj instanceof Object)) return obj 
    //如果形参obj是数组,就创建数组,如果是对象就创建对象
    let objCopy = obj instanceof Array ? [] : {}  

    for(let key in obj){  
        if(obj instanceof Object){  
            objCopy[key] = deepCopy(obj[key])  
        } else{  
            if(obj.hasOwnProperty(key)){  
                objCopy[key] = obj[key]  
            }
        }  
    }  
    return objCopy  
}  

4.promise

解决回调地狱的问题

有三种状态:

pending fulfilled(成功) rejected(失败)

状态改变只能从pending到另外两种 且不能再改变

对象的实例化方法:

then catch finally

then:

指定用于得到成功value的成功回调和失败回调,返回新的promise实例化对象

成功的状态:执行then的第一个回调函数

失败的状态:执行then方法的第二个回调函数

then方法的返回值的promise实例化对象的状态取决于回调函数中的内容

返回非promise实例化对象,得到成功的promise

抛出异常,得到失败的promise

返回promise实例化对象,则该对象的状态和结果值影响result常量的结果值

const p1=new Promise( (resolve,reject)=>{
    resolve('ok');
})
const result=p1.then(value=>{
      return value;   //状态fulfilled 结果value
      return new Promise((resolve,reject)=>{
             reject('error')   //状态rejected 结果error
             resolve('ok')     //状态fulfilled 结果ok
      })  
      throw'异常信息'     //状态rejected 结果异常信息 
},reason =>{
      console.log(reason);
})
链式调用

then的执行依赖上一步结果

catch方法:

与then方法类似

可以专门指定失败的回调函数

返回一个Promise对象,返回对象的状态与then方法里一样

const result=p1.catch( reason =>{
         console.log(reason)
         return reason
         return new Promise( (resolve,reject) =>{
                  resolve('ok')
                  reject('error')
         }) 
})

可以和then方法结合使用

错误穿透

如果有多个需要执行的成功回调,可以不每一次都写失败回调,一次性使用最后的catch

p1.then( value => {
    console.log(value);
}).then( value => {
     console.log(value);
}).catch( reason => {
     console.log(reason); 
})
finally方法(ES9新增):

Promise对象无论成功失败都会执行

回调函数不接受参数

const p1=new Promise( (resolve,reject) =>{
    resolve('ok');
})
p1.then( value => {
    console.log(value);
}).catch( reason => {
   console.log(reason);
}).finally( ( )=> {
    console.log('最终....');
})
all方法:

针对于多个promise的异步任务的处理

接受一个数组类型的参数,数组里放的是多个promise实例化对象

返回值:promise对象,状态由数组里的所有promise决定

所有promise都成功,结果成功,结果值由每一个promise的结果值组成

只要有一个失败的就失败,结果值是失败的这个promise的结果

allSettled方法:

接收数组为参数,都有结果了就执行,无论成功失败

用来确定一组异步操作是否都结束了

any方法:

接收数组为参数,只要有一个状态为成功就成功

race方法:

传参为数组

状态和结果以最先到达的为准

reject方法:

返回一个状态为rejected的Promise对象

参数只影响Promise结果

resolve方法:

返回一个状态为resolve的Promise对象

将一个普通的值转化为Promise类型的数据

参数为非Promise对象,返回成功的Promise对象

参数为Promise对象,返回对象的状态取决于参数对象

终止Promise链条

基于then的链式调用

返回一个pending状态的Promise实例

return new Promise( ( ) => { })

一个Promise实例对象指定多个成功/失败的回调函数,都会调用,只要状态不是pending

5.async

任何函数都可以被声明成一个async函数

目的是在内部执行异步的功能,并且得到结果数据值

async function main(){
    return 100; //返回非Promise对象的数据 得到成功Promise
    return new Promise()    //得到的状态取决于这个Promise的状态
    throw '出错'  //得到失败的Promise
}
let result=main()  //调用
result.then(
value =>{}
,reason =>()
)

await表达式

async函数中不一定有await表达式

但有await的函数一定是async函数

await相当于then,可以直接拿到成功的Promise实例化对象的结果值

内部执行异步的功能,并且得到成功的结果数据值

async function main(){
      //await右侧是非Promise类型的数据,得到的结果就是await后面的值
      let rs=await 100;
      console.log(rs);  //100

      //await右侧是Promise成功类型的数据
      let rs=await new Promise ( (resolve,reject) => {
            resolve('ok');
            reject('error')  //接收不到
      })
      console.log(rs)

      //await右侧是Promise失败类型数据,需要try..catch来捕获
      try {
          let rs=await Promise.reject('error');
          console.log(rs);
      } catch (e) {
          console.log(e);
      }
      console.log(..); //有try catch后面的代码将继续执行
}
main()
await表达式的执行顺序问题

同步异步代码同时出现,先执行同步,再执行异步

async function main(){
   console.log(1);
   let result=await Promise.resolve('ok');
   console.log(2);
   let result1=await Promise.resolve('okk');
   console.log(result1)
}
main()
console.log(3)

输出顺序:1 3 ok 2 okk