JS基础知识

new实现过程及源码

  1. 创建一个空对象
  2. 将空对象的隐式原型(_proto_)连接到构造函数的原型上
  3. 执行构造函数
  4. 返回这个对象
function myNew(fun){
    retrun function(){
        //创建一个空对象,并将其隐式原型指向构造函数的原型
        let obj ={
            __proto__ = fun.protoType
        }
        //执行构造函数
        fun.call(obj,...arguments)
        //返回该函数
        return obj
    }
}

function person(name,age){
    this.name = name
    this.age = age
}
console.log(myNew(person)('zs',13)) //{name:'zs',age:13}

call apply bind 的理解与区别

  1. call apply bind 都是函数的方法,所以需要函数调用
  2. call 和apply 都是改变this的指向,而bind 式绑定this的指向,然后放回一个新函数
  3. bind 返回对应的方法不会立即执行,调用时才执行,call 和apply是立即执行对的
     let dog = {
            name: '狗',
            say() {
                console.log('我是:' + this.name)
            },
            eat(food) {
                console.log('喜欢吃:' + food)
            }
        }
        let cat = {
            name: '猫'
        }
        dog.say.call(cat)
        dog.eat.call(cat, '鱼')

call 的第一个参数:指的是this指向的对象,接下来的参数是需要传递的参数

apply的第一个参数:指的是this指向的对象,接下来的第二参数是一个参数的集合

bind的第一个参数:指的是this指向的对象,接下来的参数是需要传递的参数

对数组操作的几种常见方法及其返回值

改变原数组的方法(7个):

  1. pop(): 删除一个数组中的最后的一个元素,并返回这个元素

  2. shift(): 删除数组的第一个元素,并返回这个元素

  3. push(): 向数组的末尾添加元素,并返回新的长度

  4. unshift(): 向数组的开头添加一个或更多元素,并返回新的长度

  5. reverse(): 颠倒数组中元素的顺序

  6. splice(): 添加/删除数组元素,然后返回被删除的项目

  7. sort(): 数组排序,并返回这个数组

不改变原数组的方法(8个)

ES5: join、slice、cancat、indexOf、lastIndexOf、
ES7: includes

  1. join(): 数组转字符串
  2. slice(): 浅拷贝数组的元素,选择的数组的一部分浅拷贝到一个新数组对象
  3. cancat(): 方法用于合并两个或多个数组,返回一个新数组
  4. indexOf(): 查找数组是否存在某个元素,返回下标
  5. lastIndexOf(): 查找指定元素在数组中的最后一个位置
  6. includes(): 查找数组是否包含某个元素 返回布尔

遍历方法(12个):

js中遍历数组并不会改变原始数组的方法总共有12个:

ES5:forEach、every 、some、 fliter、map、reduce、reduceRight、
ES6:find、findIndex、keys、values、entries

闭包

  1. 什么是闭包:由于变量作用域的关系,一个函数外部是无法访问一个函数内部的变量。当一个函数能够访问到另一个函数内部的变量的时候,我们就称这个函数形成了闭包

  2. 优点:能够延长变量的生命周期,可以重复利用变量,并且还不会造成变量的污染

  3. 缺点:会造成内存泄漏

  4. 常用闭包的三种方式:

    • 返回值:最常用的一种形式是函数作为返回值被返回
    • 函数赋值:一种变形的形式是将内部函数赋值给一个外部变量
    • 函数参数:闭包可以通过函数参数传递函数的形式来实现
    //第一种:返回值  最常用的一种形式是函数作为返回值被返回
            var F1 = function () {
                var b = 'local';
                var N = function () {
                    return b;
                }
                return N;
            }
            console.log(F1()());
    //第二种:函数赋值   一种变形的形式是将内部函数赋值给一个外部变量
            var inner;
            var F2 = function () {
                var b = 'local';
                var N = function () {
                    return b;
                };
                inner = N;
            };
            F2();
            console.log(inner());
    
    //第三种: 函数参数   闭包可以通过函数参数传递函数的形式来实现
            var Inner = function (fn) {
                console.log(fn());
            }
            var F3 = function () {
                var b = 'local';
                var N = function () {
                    return b;
                }
                Inner(N);
            }
            F3();
    

垃圾回收机制

V8引擎垃圾回收机制详解

浏览器的垃圾回收机制是利用了V8引擎的垃圾回收机制

主要就是将内存划分为两个区域,新生代老年代

新生代

大多数对象开始都会被分配到这个这里,新生代空间比较小,在64位的操作系统下,应该只有64兆,在32位的系统下只有32兆。

新生代的垃圾回收机制主要采用scavenge[ˈskævəndʒ] 算法,这种算法是一种典型的牺牲空间换取时间的算法。它将新生代内存一分为二,其中一块是放着存活的对象,是semi [ˈsemi] space from ,另一块是空闲的,是 semi space to。当from 空间快满的时候,会把from 空间的存活的对象打上标记 copy到to空间,销毁失活的对象。当复制完成之后,from 空间和 to 空间完成了一次角色对换。旧的from 空间变成新的to 空间,旧的to 空间,变成新的from空间。

老年代

老年代的空间就比较到,在64位的操作系统里面是1400兆,在32位操作系统里面是32兆。这里面的对象的生命周期比较长。在新生代里面经过一次循环的,并且空间占to内存25%的对象。

老年代采用的是Mark-Sweep(标记清除)和Mark-Compact(标记整理)来进行管理。

过程:标记清除阶段会遍历所有的对象,并标记活着的对象,在随后的清除阶段,只销毁没有被标记的对象。这里会有一个问题就是:这里在销毁失活的对象的之后,内存空间会存在不连续的状态。对后续的内存分配会造成问题。所以此时就需要用到标记整理,标记整理会在整理的过程中,将存活的对象往一端移动,移动完成之后,直接清理掉边境外的内存。

跨域

  1. 什么是同源策略?

    同源策略是浏览器最基本的安全策略。同源也就是指协议、域名、端口都相同。

  2. 什么是跨域?

    跨域就是指协议、域名、端口中一个或者都不相同。

  3. 怎么解决跨域?

    • jsonp 的方法: 动态创建script标签,,利用script 标签中的src 不受同源策略的影响,将src指向第三方的api网址,并提供一个回调函数来接受数据。

      缺点:jsonp 只能支持get请求,不能支持post请求

    • 反向代理:Proxy 因为同源策略只存在浏览器端,但是不在服务器端。此时我们只需配置一个代理服务器,代理服务器的协议、域名、端口和我们的浏览器相同,利用代理服务器和目标服务器直接发送请求,解决跨域问题。

      ​ vue2.0 的项目我们都是在vue.confign.js设置devserve 中proxy来配置反项代理

    • CORS:在服务器端设置响应头中Access-Control-Allow-Origin*

事件循环(EventLoop)

因为js是单线程运行的,所以js会先在执行栈中运行同步代码,当js遇到异步代码的时候,就会丢给浏览器,浏览器是多线程的,可以同时运行多个程序,当浏览器发现异步代码要运行的时候,就会丢到事件队列里面,事件队列里面有宏任务和微任务的区别。当js主线程的代码执行完之后,就会去执行事件队列里面的任务。

微任务:promise.then process.nextTick(node环境下的)

宏任务:setInterval setTimeout setImmediate

执行顺序:同步代码 process.nextTick 微任务 宏任务 setImmediate

浏览器渲染机制

  1. 浏览器会根据html 和css 构建DOM树和CSSOM (css样式表)
  2. 然后根据DOM树和CSSOM生成渲染树(Render树)
  3. 根据render树进行布局,定位坐标大小,是否显示隐藏,确定是否换行等
  4. 然后调用浏览器底层的api,使页面展示在屏幕上

防抖(debounce)

防抖:解决高频率事件,相当于延迟触发,也就是说事件处理函数在一段时间之后触发

应用场景:

  1. 搜索框输入查询
  2. 按钮提交事件

简版

function debounce (fn,delay){
    let timer = null
    return function(){
        if(timer){
            clearTimeout(timer)
        }
        timer = setTimeout(()=>{
            fn.call(this,...arguments)
        })
    }
}

复杂版:

function debounce(fun, wait, immediate) {
    let timeout, result
    debounced = function () {
        //清除定时器
        clearTimeout(timeout)
        //解决this指向问题
        let _this = this
        //解决event(事件对象) 指向问题
        let args = arguments
        if (immediate) {
            //立即执行
            let callNow = !timeout
            timeout = setTimeout(() => {
                timeout = null
            }, wait)
            if (callNow) result = fun.apply(_this, args)

        } else {
            //不会立即执行
            timeout = setTimeout(function () {
                fun.apply(_this, args)
            }, wait)
        }
        return result
    }
    debounced.cancel = function () {
        clearTimeout(timeout)
        timeout = null
    }
    return debounced
}

节流(throttle)

节流:解决高频率事件,相当于稀释事件频率,也就是说事件处理函数在一段时间之内只触发一次

应用场景:

  1. DOM元素的拖拽功能实现

  2. 监听scroll滚动事件

  3. 点赞功能,一秒钟只能执行一次

    function throttle(fn, delay) {
                let flag = true
                return function () {
                    if (flag) {
                        setTimeout(() => {
                            fn.call(this, ...arguments)
                            //因为是setTimeout是宏任务,所以会此处的代码会比下面的flag = false 晚执行
                            flag = true
                        }, delay)
                    }
                    flag = false
                }
            }
    

浏览器缓存(http 缓存)

最大的区别就是判断缓存命中时,浏览器是否需要向服务器进行询问,来协商缓存的相关信息

强制缓存

最早的时候时利用exprise,来判断缓存是否过期哦,如果没有就直接复用,但是这种方式会有问题,就是exprise 时时间戳,会存在服务器的时间和客户端的时间不同步的情况。所以推荐是使用max-age 来控制。这是只滑动的时间

cache-control:max-age-3153600

协商缓存

协商缓存,就是指在使用本地缓存之前,需要向服务器发送一次get请求,与之协商当前浏览器保存的缓存是否过期,如果没有过期,服务器会返回304,如果过期了,则会返回最新的数据回来。

协商缓存是通过响应头中etag和last-modified进行控制的

last-modified:上一次修改时间

etag:资源对应的唯一字符串

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值