javaScript总结(16-20)

十六、说说new操作符具体都干了什么?

1.new是什么?
new操作符可以创建给定函数的实例对象。
new通过构造函数创建出来的实例可以访问到构造函数中的属性和构造函数原型链中的属性。
2.new流程

  1. 创建一个新的对象obj
  2. 将对象与构造函数通过原型链连接起来
  3. 将构造函数中的this绑定到新建的对象obj上
  4. 根据构造函数返回类型做判断,如果是原始值则被忽略,如果是对象,则正常处理。
    请添加图片描述
    3.手写new
    根据上述流程我们可以手写出一个new函数

function mynew(func,…args) {
//创建一个新对象
let obj = {};
//2.新对象原型指向构造函数原型对象
obj.proto = func.prototype;
//3.执行构造函数,将新对象绑定给this
let result = func.apply(obj,args);
//4.判断返回值是否是对象,如果是则返回,如果不是则返回新对象
return typeof result === ‘object’ ? result : obj;
}

小结:new是用来通过构造函数创建实例对象的,通过new创建的实例对象,可以调用该构造函数的属性以及其原型链上的属性。new操作流程第一步,先创建一个新对象,第二步,将该对象的原型指向构造函数的原型对象,第三步,将构造函数的this绑定给创建的新对象,第四步,判断返回值如果返回值是原始值,则返回原始值,如果返回值是对象,则返回新对象。

十七、Ajax 原理是什么?如何实现?

1.全称Async Javascript and XML
即异步的javascript和xml,是一种 创建交互式网页应用的网页开发技术,可以在不重新加载整个网页的情况下、与服务器交换数据,并且更新部分网页。
Ajax的原理简单来说就是通过XmlHttpRequest对象来向服务器进行异步请求,从服务器获取数据,然后通过Javascript来操作DOM来更新页面。

2.实现 Ajax异步交互需要服务器逻辑进行配合,需要完成以下步骤:

  1. 创建 Ajax的核心对象 XMLHttpRequest对象
  2. 通过 XMLHttpRequest 对象的 open() 方法与服务端建立连接
  3. 构建请求所需的数据内容,并通过XMLHttpRequest 对象的 send() 方法发送给服务器端
  4. 通过 XMLHttpRequest 对象提供的 onreadystatechange 事件监听服务器端你的通信状态
  5. 接受并处理服务端向客户端响应的数据结果
  6. 将处理结果更新到 HTML页面中
//创建 Ajax的核心对象 XMLHttpRequest对象
const xhr = new XMLHttpRequest();
//与服务器建立连接
xhr.open('GET', 'http://121.199.0.35:8888/index/carousel/findAll', true);
//发送请求
xhr.send();
//监听服务器返回的状态
xhr.onreadystatechange = function (e) {
    if (xhr.readyState === 4) { 
        // 整个请求过程完毕
        //readyState=4:响应的内容解析完毕,可以在客户端使用了--完成
        //status=200:服务器正常响应 
        if (xhr.status >= 200 && xhr.status <= 300) {
            console.log(xhr.responseText) // 服务端返回的结果
        } else if (xhr.status >= 400) {
            console.log("错误信息:" + xhr.status)
        }
    }
}

3.封装ajax

//封装一个ajax请求
function ajax(options) {
    //创建XMLHttpRequest对象
    const xhr = new XMLHttpRequest()

    //初始化参数的内容
    options = options || {}
    options.type = (options.type || 'GET').toUpperCase()
    options.dataType = options.dataType || 'json'
    const params = options.data

    //发送请求
    if (options.type === 'GET') {
        xhr.open('GET', options.url + '?' + params, true)
        xhr.send(null)
    } else if (options.type === 'POST') {
        xhr.open('POST', options.url, true)
        xhr.send(params)

    //接收请求
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            let status = xhr.status
            if (status >= 200 && status < 300) {
                options.success && options.success(xhr.responseText, xhr.responseXML)
            } else {
                options.fail && options.fail(status)
            }
        }
    }
}

小结:Ajax全称Async javascript and xml 即异步的javascript和xml,简单来说就是通过xmlHttpRequest发起网络请求,从服务器获取数据,通过javascript操作DOM渲染数据。操作流程为1、先初始化XmlHttpRequest实例,、通过实例的open方法携带发送方法method、路径url、是否异步async等参数,3、通过实例的send方法发送出去,send可以携带请求参数,如果是get请求send参数为空。4、通过onreadystatuschange监听请求状态,如果状态为4表示请求发送完成,我们可以对不同的请求返回状态码进行操作处理。5、最后将处理结果更新到页面。

十八、bind、call、apply 区别?如何实现一个bind?

call、apply、bind作用是改变函数执行时的上下文,简而言之就是改变函数运行时的this指向。
apply
apply接受两个参数,第一个参数是this的指向,第二个参数是函数接受的参数,以数组的形式传入
改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次

function fn(...args){
    console.log(this,args);
}
let obj = {
    myname:"张三"
}

fn.apply(obj,[1,2]); // this会变成传入的obj,传入的参数必须是一个数组;
fn(1,2) // this指向window

当第一个参数为null、undefined的时候,默认指向window(在浏览器中)

fn.apply(null,[1,2]); // this指向window
fn.apply(undefined,[1,2]); // this指向window

call
call方法的第一个参数也是this的指向,后面传入的是一个参数列表

跟apply一样,改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次

function fn(...args){
    console.log(this,args);
}
let obj = {
    myname:"张三"
}

fn.call(obj,1,2); // this会变成传入的obj,传入的参数必须是一个数组;
fn(1,2) // this指向window

同样的,当第一个参数为null、undefined的时候,默认指向window(在浏览器中)

fn.call(null,[1,2]); // this指向window
fn.call(undefined,[1,2]); // this指向window

bind
bind方法和call很相似,第一参数也是this的指向,后面传入的也是一个参数列表(但是这个参数列表可以分多次传入)

改变this指向后不会立即执行,而是返回一个永久改变this指向的函数

function fn(...args){
    console.log(this,args); } let obj = {
    myname:"张三" }

const bindFn = fn.bind(obj); // this 也会变成传入的obj ,bind不是立即执行需要执行一次 bindFn(1,2) // this指向obj fn(1,2) // this指向window

实现bind的步骤,我们可以分解成为三部分:
修改this指向
动态传递参数

// 方式一:只在bind中传递函数参数
fn.bind(obj,1,2)()

// 方式二:在bind中传递函数参数,也在返回函数中传递参数
fn.bind(obj,1)(2)

兼容new关键字

Function.prototype.myBind = function (context) {
    // 判断调用对象是否为函数
    if (typeof this !== "function") {
        throw new TypeError("Error");
    }

    // 获取参数
    const args = [...arguments].slice(1),
          fn = this;

    return function Fn() {

        // 根据调用方式,传入不同绑定值
        return fn.apply(this instanceof Fn ? new fn(...arguments) : context, args.concat(...arguments)); 
    }
    }

小结:call,apply,bind都是用来改变this指向的,但是他们之间也有些不同,
call第一个参数是this指向,后面的是参数列表。这个函数使用后会立即调用一次,并且修改的this指向是临时的。
apply第一个参数也是this指向,第二个参数是函数接收的参数,以数组的形式传入,修改后会立即调用一次,并且修改的this指向也是临时的。
bind第一个参数同样是this的指向,后面的参数是函数的参数列表,不会立即调用,而是会返回一个永久更改this指向的新函数。

十九、说说你对JavaScript中事件循环的理解​

1.是什么
JavaScript 在设计之初便是单线程,即指程序运行时,只有一个线程存在,同一时间只能做一件事

为什么要这么设计,跟JavaScript的应用场景有关

JavaScript 初期作为一门浏览器脚本语言,通常用于操作 DOM ,如果是多线程,一个线程进行了删除 DOM ,另一个添加 DOM,此时浏览器该如何处理?

为了解决单线程运行阻塞问题,JavaScript用到了计算机系统的一种运行机制,这种机制就叫做事件循环(Event Loop)
2.在JavaScript中,所有的任务都可以分为

同步任务:立即执行的任务,同步任务一般会直接进入到主线程中执行
异步任务:异步执行的任务,比如ajax网络请求,setTimeout定时函数等
如果将任务划分为同步任务和异步任务并不是那么的准确,举个例子:

console.log(1)

setTimeout(()=>{
    console.log(2)
}, 0)

new Promise((resolve, reject)=>{
    console.log('new Promise')
    resolve()
}).then(()=>{
    console.log('then')
})

console.log(3)

实际结果是:1=>‘new Promise’=> 3 => ‘then’ => 2
出现分歧的原因在于异步任务执行顺序,事件队列其实是一个“先进先出”的数据结构,排在前面的事件会优先被主线程读取

例子中 setTimeout回调事件是先进入队列中的,按理说应该先于 .then 中的执行,但是结果却偏偏相反

原因在于异步任务还可以细分为微任务与宏任务

微任务
一个需要异步执行的函数,执行时机是在主函数执行结束之后、当前宏任务结束之前
常见的微任务有:
Promise.then
MutaionObserver
Object.observe(已废弃;Proxy 对象替代)
process.nextTick(Node.js)

宏任务
、宏任务的时间粒度比较大,执行的时间间隔是不能精确控制的,对一些高实时性的需求就不太符合
常见的宏任务有:
script (可以理解为外层同步代码)
setTimeout/setInterval(定时器#重点)
UI rendering/UI事件
postMessage、MessageChannel
setImmediate、I/O(Node.js)

图片来源:https://mp.weixin.qq.com/s/9iN7XR1PwXfua8SrabOi5w
按照这个流程,它的执行机制是:

执行一个宏任务,如果遇到微任务就将它放到微任务的事件队列中
当前宏任务执行完成后,会查看微任务的事件队列,然后将里面的所有微任务依次执行完

console.log(1)
setTimeout(()=>{
    console.log(2)
}, 0)
new Promise((resolve, reject)=>{
    console.log('new Promise')
    resolve()
}).then(()=>{
    console.log('then')
})
console.log(3)

流程如下

// 遇到 console.log(1) ,直接打印 1
// 遇到定时器,属于新的宏任务,留着后面执行
// 遇到 new Promise,这个是直接执行的,打印 'new Promise'
// .then 属于微任务,放入微任务队列,后面再执行
// 遇到 console.log(3) 直接打印 3
// 好了本轮宏任务执行完毕,现在去微任务列表查看是否有微任务,发现 .then 的回调,执行它,打印 'then'
// 当一次宏任务执行完,再去执行新的宏任务,这里就剩一个定时器的宏任务了,执行它,打印 2

小结:事件循环,在javascript设计之初就是单线程(因为js多用来操作dom,如果是多线程一个删除dom一个添加dom,浏览器就无法处理),也就是说在程序运行中同一时间只允许有一个任务进行,如果有耗时任务的话就会运行缓慢,为了解决单线程运行阻塞问题,JavaScript用到了计算机系统的一种运行机制,这种机制就叫做事件循环。它包括同步任务和异步任务,异步任务又分为宏任务和微任务,宏任务例如script(外层同步代码),setTimeout等,微任务包括Premise.then等。

小练习:

async function async1() {
    console.log('async1 start')
    await async2()
    console.log('async1 end')
}
async function async2() {
    console.log('async2')
}
console.log('script start')
setTimeout(function () {
    console.log('settimeout')
})
async1()
new Promise(function (resolve) {
    console.log('promise1')
    resolve()
}).then(function () {
    console.log('promise2')
})
console.log('script end')

执行整段代码,遇到 console.log(‘script start’) 直接打印结果,输出 script start
遇到定时器了,它是宏任务,先放着不执行 遇到 async1(),执行 async1 函数,先打印 async1
start,下面遇到await怎么办?先执行 async2,打印 async2,然后阻塞下面代码(即加入微任务列表),跳出去执行同步代码
跳到 new Promise 这里,直接执行,打印 promise1,下面遇到 .then(),它是微任务,放到微任务列表等待执行
最后一行直接打印 script end,现在同步代码执行完了,开始执行微任务,即 await下面的代码,打印 async1 end
继续执行下一个微任务,即执行 then 的回调,打印 promise2 上一个宏任务所有事都做完了,开始下一个宏任务,就是定时器,打印
settimeout 所以最后的结果是:script start、async1 start、async2、promise1、script
end、async1 end、promise2、settimeout

二十、说说你对正则表达式的理解?应用场景?

1.正则表达式是一种用来匹配字符串的强有力的武器

它的设计思想是用一种描述性的语言定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的
在 JavaScript中,正则表达式也是对象,构建正则表达式有两种方式:

//字面量创建,其由包含在斜杠之间的模式组成
const re = /\d+/g;
//调用RegExp对象的构造函数
const re = new RegExp("\\d+","g");

const rul = "\\d+"
const re1 = new RegExp(rul,"g");

2.校验规则:
常用规则
![在这里插入在这里插入图片描述
正则表达式标记
在这里插入图片描述
3.匹配方法
正则表达式常被用于某些方法,我们可以分成两类:

字符串(str)方法:match、matchAll、search、replace、split
正则对象下(regexp)的方法:test、exec
在这里插入图片描述

小结:正则表达式通常原来校验字符串格式是否符合定义的规则,常用来表单校验,手机号、身份证号等,经常使用的方法有test、repalce、match、exec等

注意:学习总结
参考链接:https://github.com/febobo/web-interview

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值