美文网首页
原生JS相关

原生JS相关

作者: zhenghongmo | 来源:发表于2019-12-06 17:42 被阅读0次

    1.ES6语法

    • let const 箭头函数 Promise 展开操作符 默认参数 import export

    2.Promise、Promise.all、Promise.race 分别怎么用

    • Promise 用法
    function fn(){
      return new Promise((resolve, reject) => {
          成功时调用 resolve(数据)
          失败时调用 reject(错误)
      })
    }
    
    fn().then(success, fail).then(success1, fail1)
    
    • Promise.all 用法
    Promise.all([promise1, promise2]).then(success1, fail1)
    只有 promise1 和 promise2 都成功才会调用success1
    
    • Promise.race用法
    Promise.race([promise1, promise2]).then(success1, fail1)
    promise1 和 promise2 只要有一个成功就会调用success1
    

    3. 手写函数防抖和函数节流

    • 防抖
      一段时间会等,然后带着一起做了
    function delays (fn, delay){
      let timerId = null
      return function (){
          const context = this
          if(timeId){ 
              window.clearTimeout(timeId) 
          }
          timeId = setTimeout(() => {
              fn.apply(context, arguments)
              timeId = null
          }, delay)
      }
    }
    const delayed = delays(() => {console.log("lalalla")})
    delayed() 
    delayed()
    
    • 节流
      一段时间执行一次后,就不执行第二次了
    function throttle(fn, delay){
      let canUse = true
      retuen function() {
          function() {
            if(canUse){
                fn.apply(this,arguments)
                canUse = false
                setTimeout(() => {
                    canUse = true
                }, delay)
            }
          }
      }
    }
    const throttled = throttle(() => {console.log("lskllsl")})
    throttled()
    throttled()
    

    4.手写AJAX

    var request = new XMLHttpRequest()
    request.open('GET', 'a/b/c?name=mm', true)
    request.onreadystatechange = function () {
      if(request.readyState === 4 && request.status === 200) {
        console.log(request.responseText)
      }
    }
    request.send() //post请求body放在这里面
    

    5.this问题

    this 就是你 call 一个函数时,传入的第一个参数(this 就是 call 的第一个参数 fn.call(this, n1,n2))

    • fn()
      this => window/global
    • obj.fn()
      this => obj
    • fn.call(xx, arguments)
      this => xx
    • fn.apply(xx)
      this => xx
    • fn.bind(xx)
      this => xx
    • new Fn()
      this => 新的对象
    • fn = () => {}
      this => 外面的this
      this

    6. 闭包

    闭包

    函数调用了函数之外的变量

    !function () {
      //两个闭包 函数+变量
      var lives = 50
      window.addlive = function () {
        lives += 1
      }
      window.dielive = function () {
          lives -=1
      }
    }()
    
    • 内存泄漏:你用不到(访问不到)的变量,依然占据着内存空间,不能被再次利用起来。闭包不会造成内存泄漏

    7. 立即执行函数

    立即执行函数:声明一个匿名函数,马上调用这个匿名函数

    • 写法
    (function(){alert('我是匿名函数')} ()) // 用括号把整个表达式包起来
    (function(){alert('我是匿名函数')}) () //用括号把函数包起来
    !function(){alert('我是匿名函数')}() // 求反,我们不在意值是多少,只想通过语法检查。
    +function(){alert('我是匿名函数')}()
    -function(){alert('我是匿名函数')}()
    ~function(){alert('我是匿名函数')}()
    void function(){alert('我是匿名函数')}()
    new function(){alert('我是匿名函数')}()
    

    创建一个独立的作用域
    这个作用域里面的变量,外面访问不到(避免变量污染)

    var liList = ul.getElementsByTagName('li')
    for(var i=0; i<6; i++){
      liList[i].onclick = function(){
        alert(i) // 为什么 alert 出来的总是 6,而不是 0、1、2、3、4、5
      }
    }
    
    ---------用立即执行函数给每个 li 创造一个独立作用域,在立即执行函数执行的时候,i 的值被赋值给 ii,此后 ii 的值一直不变--------
    
    var liList = ul.getElementsByTagName('li')
    for(var i=0; i<6; i++){
      !function(ii){
        liList[ii].onclick = function(){
          alert(ii) // 0、1、2、3、4、5
        }
      }(i)
    }
    

    8.JSONP、 CORS 、跨域?

    JSONP

    • 同源策略:浏览器处于安全方面的考虑,只允许与同域下的接口交互

    • 同域:
      1.同协议: 如都是http或都是https
      2.同域名: 如都是baidu.com/a和baidu.com/b (用户打开baidu.com/a,当前页面下的js向baidu.com/b的接口发ajax请求,浏览器是允许的。但假如想jianshu.com/b发ajax请求就会被浏览器阻止,因为存在跨域调用)
      3. 同端口: 如都是80端口

    • JSONP(创建动态JavaScript)
      通过 script 标签加载数据的方式去获取数据当做 JS 代码来执行。
      提前在页面上声明一个函数,函数名通过接口传参的方式传给后台,后台解析到函数名后在原始数据上「包裹」这个函数名,发送给前端。换句话说,JSONP 需要对应接口的后端的配合才能实现。

    <script>
    function yyy(ret){
    console.log(ret);
    }
    </script>
    <script src="api.xxx.com/weather?callbackName=yyy"></script>
    --------------------------------------------------------------------------------------------------
    这个请求到达后端后,后端会去解析callback这个参数获取到字符串yyy,在发送数据做如下处理:
    之前后端返回数据: {"city": "hangzhou", "weather": "晴天"}
    现在后端返回数据: yyy({"city": "hangzhou", "weather": "晴天"})
    前端script标签在加载数据后会把 「yyy({"city": "hangzhou", "weather": "晴天"})」做为 js 来执行,
    这实际上就是调用yyy这个函数,同时参数是 {"city": "hangzhou", "weather": "晴天"}。
    
    • 突破同源策略 === 跨域
    • CORS跨域(加响应头)
      response.setHeader('Access-Control-Allow-Origin', 'http://xxx.com:8001')

    9. async/await怎么用,如何捕获异常?

    async函数

    • promise
    function fn() {
      return new Promise ( (resolve, reject) => {
        setTimeout(() => {
          let n = parseInt(Math.random()*6 + 1)  //[0-1)*6+1后取整
          resolve(n)
        },3000)
      })
    }
    
    fn() .then( 
    //成功调用resolve()
    (x) => {
      console.log(x) //这里的x就是上面的n
    },
    //失败调用reject()
    () => {
      console.log(失败) 
    }
    )
    
    • await只能放在async函数里面, await命令后面是一个 Promise 对象,返回该对象的结果
    • async可以声明一个异步函数, 返回一个Promise 对象
    • 把异步代码写成同步代码。
    function fn(params) {
      return new Promise ( (resolve, reject) => {
        setTimeout(() => {
          let n = parseInt(Math.random()*6 + 1)  //[0-1)*6+1后取整
          if(n>3){
              if(params==="大"){
                resolve(n)
              }else{
                reject(n)
              }
            }else{
               if(params==="小"){
                resolve(n)
              }else{
                reject(n)
              }
            }
        },3000)
      })
    }
    
    async function test() {
        try{
            let n = await  Promise.all([fn("大"), fn("小")])
            console.log(n)
        }catch(error){              //捕获reject()
            console.log(error)
        }
    }
    let result = test ()
    console.log(result) //打印出一个Promise
    

    10. 如何实现深拷贝?

    • json实现深拷贝
    var a = {...}
    var b = JSON.parse(JSON.stringify(a))
    

    缺点:JSON 不支持函数、引用、undefined、RegExp、Date……

    • 递归拷贝
     function clone(object){
         var object2
         if(! (object instanceof Object) ){
             return object
         }else if(object instanceof Array){
             object2 = []
         }else if(object instanceof Function){
             object2 = eval(object.toString())
         }else if(object instanceof Object){
             object2 = {}
         }
         你也可以把 Array Function Object 都当做 Object 来看待,参考 https://juejin.im/post/587dab348d6d810058d87a0a
         for(let key in object){
             object2[key] = clone(object[key])
         }
         return object2
     }
    

    11.JS数据类型

    • string number bool undefined null object symbol
    • object 包括了数组、函数、正则、日期等对象

    12. 如何用正则实现 string.trim()

    function trim(string){
        return string.replace(/^\s+|\s+$/g, ' ')
    }
    

    13. 如何实现数组去重?

    • 计数排序
     var a = [4,2,5,6,3,4,5]
     var hashTab = {}
     for(let i=0; i<a.length;i++){
         if(a[i] in hashTab){
             // 什么也不做
         }else{
             hashTab[ a[i] ] = true
         }
     }
     //hashTab: {4: true, 2: true, 5: true, 6:true, 3: true}
     console.log(Object.keys(hashTab)) // ['4','2','5','6','3']
    
    • Set去重
      • Set对象允许存储任何类型的唯一值,无论是原始值或者是对象引用
        Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组
    let  a = [4,2,5,6,3,4,5]
    let  b = new Set(a) //返回Set对象 {4, 2, 5, 5, 4, 3}
    //将Set对象转化成数组
    Array.from(b)   //方法一
    [...b]   //方法二
    
    • 使用 WeakMap???

    14. JS原型

    原型链

    • 举例
    var a = [1, 2, 3]
    只有0, 1, 2, length 4个key
    为什么可以a.push(4) , push是哪来的?
    a.__proto__ === Array.prototype
    push就是沿着a.__proto__ 找到的,也就是Array.prototype.push
    Array.prototype还有很多方法,如join、pop、slice、splice
    //join(): 将数组的元素组起一个字符串,console.log(a.join("-")); // 1-2-3
    //pop():数组末尾移除最后一项,减少数组的 length 值,然后返回移除的项。
    //slice():返回从原数组中指定开始下标到结束下标之间的项组成的新数组,在只有一个参数的情况下, slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。如果有两个参数
    //splice():(1)指定 2 个参数:要删除的第一项的位置和要删除的项数。例如, splice(0,2)会删除数组中的前两项。(2)提供 3 个参数:起始位置、 0(要删除的项数)和要插入的项。例如:splice(2,0,4,6)会从当前数组的位置 2 开始插入4和6。splice (2,1,4,6)会删除当前数组位置 2 的项,然后再从位置 2 开始插入4和6。
    Array.prototype就是a的原型(__proto__)
    

    15. 继承

    • 不用class
    function Animal() {
      this.body = 'body'
    }
    Animal.prototype.move  = function() {}
    function Human (name){
        Animal.apply(this, arguments)
        this.name = name
    }
    
    //Human.prototype.__proto__ = Animal.prototype//非法
    
    var f = function () {}
    f.prototype = Animal.prototype
    Human.prototype = new f()
    Human.prototype.useTools = function() {}
    var mm = new Human()
    
    • 使用class
    class Animal{
        constructor() {
            this.body = 'body'
        },
        move() {}
    }
    class Human extends Animal{
      constructor(name){
          super()
          this.name = name
      },
    useTools() {}
    }
    let mm = new Human()
    

    16.手写promise

    promise

    手写promise

    相关文章

      网友评论

          本文标题:原生JS相关

          本文链接:https://www.haomeiwen.com/subject/pedlgctx.html