IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Web前端开发面试之JavaScript篇 -> 正文阅读

[JavaScript知识库]Web前端开发面试之JavaScript篇

1、谈谈你对MVVM开发模式的理解

答:MVVM 分为 Model、View、ViewModel 三者。

  • Model 代表数据模型,数据和业务逻辑都在Model层中定义;
  • View 代表UI视图,负责数据的展示;
  • ViewModel 负责监听 Model 中数据的改变并且控制视图的更新,处理用户交互操作;

Model 和 View 并无直接关联,而是通过 ViewModel 来进行联系的,Model 和 ViewModel 之间有着双向数据绑定的联系。因此当 Model 中的数据改变时会触发 View 层的刷新,View 中由于用户交互操作而改变的数据也会在 Model 中同步。

这种模式实现了 Model 和 View 的数据自动同步,因此开发者只需要专注对数据的维护操作即可,而不需要自己操作 dom。

vue双向绑定原理

Vue双向绑定原理
vue 数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)。

通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图。

具体步骤:
第一步: 需要observer的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter,这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化

第二步: compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图

第三步: Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:

在自身实例化时往属性订阅器(dep)里面添加自己自身必须有一个update()方法待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。

第四步: MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。

2、原型对象,构造函数,实例之间的关系?

(1)每个构造函数都有一个 prototype 属性,指向这个构造函数的原型对象。
(2)原型对象有一个 constructor 属性,指向原型对象的构造函数。
(3)实例通过 new 一个构造函数创建,实例通过 proto 可以找到构造函数的原型对象。
(4)每个原型对象都有 proto 属性,指向原型对象的上一级原型对象。

3、介绍一下原型链?(js的原型和原型链)

答:原型:所有的函数都有一个特殊的属性prototype(原型),prototype属性是一个指针,指向的是一个对象(原型对象),原型对象中的方法和属性都可以被函数的实例所共享。所谓的函数实例是指以函数作为构造函数创建的对象,这些对象实例都可以共享构造函数的原型的方法。

原型链:原型链是用于查找引用类型(对象)的属性,查找属性会沿着原型链依次进行,如果找到该属性会停止搜索并做相应的操作,否则将会沿着原型链依次查找直到结尾。常见的应用是用在创建对象和继承中。

原型链:原型对象上的属性和方法是被构造函数创建的实例所共有的,当访问一个实例的属性或方法的时候,在这个实例上本身上没有找到这个属性或方法,往原型对象上找,(通过__proto__),如果在上一级原型对象上还没找到这个属性或方法,会在这个原型对象的基础上,沿着__proto__继续往上一级原型对象查找,依次类推,直到找到一个名字匹配的属性或方法或到达原型链的末尾:null。

扩展:介绍一下作用域链?
作用域:作用域的特点就是,先在自己的变量范围中查找,如果找不到,就会沿着作用域往上找。

map 和 set

  • Map是一组键值对的结构,具有极快的查找速度 。
  • Set 和 Map 类似,也是一组 key 的集合,但不存储 value。由于 key 不能重复,所以,在 Set 中,没有重复的 key。
set:不重复的值得集合【let set = new Set([1, 2, 2, 3]) // [1, 2, 3]
add(value):添加某个值,返回 Set 结构本身。
delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
has(value):返回一个布尔值,表示该值是否为Set的成员。
clear():清除所有成员,没有返回值。—
keys():返回键名的遍历器
values():返回键值的遍历器
entries():返回键值对的遍历器
forEach():使用回调函数遍历每个成员
weakSet:成员只能是对象

4、JS继承?JS继承有哪几种方法,各自优缺点是?

https://blog.csdn.net/xuedan1992/article/details/83515342
https://www.cnblogs.com/humin/p/4556820.html

继承实现的原理?
通过原型链实现继承。

(1)借用构造函数实现继承(构造继承)
原理: 通过在子类的构造函数里面执行父类的构造函数,父类构造函数里的属性和方法就都挂载到子类的实例上面了,等于是复制父类的实例属性给子类(没用到原型)。

特点: 解决了子类实例共享父类引用属性的问题;创建子类实例时,可以向父类传递参数;可以实现多继承(call多个父类对象)

缺点: 实现部分继承。父类原型链上的属性和方法并没有被子类所继承,子类继承的只是父类构造函数里面的属性和方法。

缺点: 实例并不是父类的实例,只是子类的实例;只能继承父类的实例属性和方法,不能继承原型属性/方法;无法实现函数复用,每个子类都有父类实例函数的副本,影响性能。

(2)原型链继承
原理: 将父类的实例赋值给子类的原型对象。

特点: 非常纯粹的继承关系,实例是子类的实例,也是父类的实例;父类新增原型方法/原型属性,子类都能访问到;简单,易于实现。

缺点: 问题主要在包含引用值的原型上,一个实例改变会导致原型上内容的改变。
缺点: 要想为子类新增属性和方法,不能放到构造器中;无法实现多继承;来自原型对象的所有属性被所有实例共享;创建子类实例时,无法向父类构造函数传参。

(3)组合继承(伪经典继承,实际开发中最常用的方法)
核心: 通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
原理: 是将原型链和借用构造函数组合到一起的一种继承模式,主要思路就是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。

特点:

  • 可以继承实例属性/方法,也可以继承原型属性/方法
  • 既是子类的实例,也是父类的实例;
  • 不存在引用属性共享问题 可传参;
  • 函数可复用

缺点: 可以看出在这个过程中父类的构造函数使用了两次,一次在创建子类原型的时候,另一次是在子类构造函数内部,但是使用过程中,子类的实例属性会屏蔽原型属性,也就是说某些原型属性其实是用不上的,这造成了内存的浪费。

(4)实例继承
核心:为父类实例添加新特性,作为子类实例返回
特点:不限制调用方式,不管是new 子类()还是子类(),返回的对象具有相同的效果
缺点:实例是父类的实例,不是子类的实例;不支持多继承

(5)拷贝继承
特点:支持多继承
缺点:效率较低,内存占用高(因为要拷贝父类的属性)

(6)寄生组合继承
核心:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用

5、Promise ,没有 Promise 怎么办

ES6之Promise对象

Promise 对象是 CommonJS 工作组提出的一种规范,目的是为异步编程提供统一接口。每一个异步任务返回一个 Promise 对象,该对象有一个 then 方法,允许指定回调函数。
f1().then(f2);

一个 promise 可能有三种状态:等待(pending)、已完成(resolved,又称fulfilled)、已拒绝(rejected)。

promise 必须实现 then 方法(可以说,then 就是 promise 的核心),而且 then 必须返回一个 promise,同一个 promise 的 then 可以调用多次,并且回调的执行顺序跟它们被定义时的顺序一致。

then 方法接受两个参数,第一个参数是成功时的回调,在promise由“等待”态转换到“完成”态时调用,另一个是失败时的回调,在promise由“等待”态转换到“拒绝”态时调用。同时,then 可以接受另一个 promise 传入,也接受一个“类then”的对象或方法,即 thenable 对象。

没有 promise,可以用回调函数代替。

6、知道哪些ES6,ES7的语法

promise,await/async,let、const、块级作用域、箭头函数

let,const,箭头函数,promise,class,解构赋值,export,模版字符串,(…扩展符)

promise 和 await/async 的关系

都是异步编程的解决方案

7、 js 加载过程阻塞,解决方法

指定 script 标签的 async 属性。

如果async="async",脚本相对于页面的其余部分异步地执行(当页面继续进行解析时,脚本将被执行)。

如果不使用 async 且 defer="defer":脚本将在页面完成解析时执行。

8、 js对象类型,基本对象类型以及引用对象类型的区别

分为基本对象类型引用对象类型

(1)基本数据类型:按值访问,可操作保存在变量中的实际的值。基本类型值指的是简单的数据段。
基本数据类型有这六种:undefined、null、string、number、boolean、symbol。

(2)引用类型:当复制保存着对象的某个变量时,操作的是对象的引用,但在为对象添加属性时,操作的是实际的对象。引用类型值指那些可能为多个值构成的对象。

引用类型有这几种:Object、Array、RegExp、Date、Function、特殊的基本包装类型(String、Number、Boolean)以及单体内置对象(Global、Math)。

9、 JavaScript中的轮播实现原理?假如一个页面上有两个轮播,你会怎么实现?

图片轮播的原理就是图片排成一行,然后准备一个只有一张图片大小的容器,对这个容器设置超出部分隐藏,在控制定时器来让这些图片整体左移或右移,这样呈现出来的效果就是图片在轮播了。

如果有两个轮播,可封装一个轮播组件,供两处调用。

10、class

ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过 class 关键字,可以定义类。

11、口述数组去重

法一:indexOf 循环去重,建一个空数组,循环目标数组,判断新数组中是否有当前单参数,没有就push,有就跳过

法二:ES6 Set 去重;Array.from(new Set(array))

法三:Object 键值对去重;把数组的值存成 Object 的 key 值,比如 Object[value1] = true,在判断另一个值的时候,如果 Object[value2] 存在的话,就说明该值是重复的。

数组的常用操作

concat() 连接两个或更多的数组,并返回结果。
join() 把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。
pop() 删除并返回数组的最后一个元素
push() 向数组的末尾添加一个或更多元素,并返回新的长度。
reverse() 颠倒数组中元素的顺序。
shift() 删除并返回数组的第一个元素
slice() 从某个已有的数组返回选定的元素
sort() 对数组的元素进行排序
splice() 删除元素,并向数组添加新元素。
toSource() 返回该对象的源代码。
toString() 把数组转换为字符串,并返回结果。
toLocaleString() 把数组转换为本地数组,并返回结果。
unshift() 向数组的开头添加一个或更多元素,并返回新的长度。
valueOf() 返回数组对象的原始值。

12、箭头函数和 function 有什么区别

箭头函数根本就没有绑定自己的 this,在箭头函数中调用 this 时,仅仅是简单的沿着作用域链向上寻找,找到最近的一个 this 拿来使用。

13、new 操作符原理

  1. 创建一个类的实例:创建一个空对象 obj,然后把这个空对象的 proto 设置为构造函数的 prototype。

  2. 初始化实例:构造函数被传入参数并调用,关键字 this 被设定指向该实例 obj。

  3. 返回实例 obj。

14、bind(),apply(),call() 3种方法的区别

(1) apply:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.apply(A, arguments);即 A 对象应用 B 对象的方法。

(2)call:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.call(A, args1,args2);即 A 对象调用 B 对象的方法。

(3)bind:除了返回是函数以外,它的参数和 call 一样。

15、arguments,箭头函数获取 arguments

arguments 是类数组对象,有 length 属性,不能调用数组方法 。

可用Array.from()转换。

箭头函数可用…rest参数获取。

16、闭包

闭包函数: 声明在一个函数中的函数,叫做闭包函数。

闭包: 内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。

闭包的特点:

  1. 让外部访问函数内部变量成为可能
  2. 局部变量会常驻内存中
  3. 可以避免使用全局变量,防止全局变量污染
  4. 会造成内存泄露(有一块内存被长期占用,得不到释放)

缺点:易造成内存泄漏不会被垃圾回收机制回收

闭包的应用:
6. 模仿块级作用域。
7. 保存外部函数的变量。
8. 封装私有变量

(1)什么是闭包:

闭包是指有权访问另外一个函数作用域中的变量的函数。

闭包就是函数的局部变量集合,只是这些局部变量在函数返回后会继续存在。闭包就是就是函数的“堆栈”在函数返回后并不释放,我们也可以理解为这些函数堆栈并不在栈上分配而是在堆上分配。当在一个函数内定义另外一个函数就会产生闭包。

(2)为什么要用:

匿名自执行函数:我们知道所有的变量,如果不加上var关键字,则默认的会添加到全局对象的属性上去,这样的临时变量加入全局对象有很多坏处,比如:别的函数可能误用这些变量;造成全局对象过于庞大,影响访问速度(因为变量的取值是需要从原型链上遍历的)。除了每次使用变量都是用var关键字外,我们在实际情况下经常遇到这样一种情况,即有的函数只需要执行一次,其内部变量无需维护,可以用闭包。

结果缓存:我们开发中会碰到很多情况,设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间,那么我们就需要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部的引用,从而函数内部的值可以得以保留。

17、事件委托(事件代理)

DOM事件流:事件捕获,目标阶段,事件冒泡
addEventListener(‘click’,function(event){触发事件}, false)默认在事件冒泡阶段触发,默认值false
事件委托:event.currentTarget:事件绑定的元素(绑定在父级元素)
event.target:触发事件的源头(所点击的子元素)
target:事件目标

事件委托利用了事件冒泡和event.target,当有一系列子元素都需要绑定事件时,只需要将事件绑定在父元素即可 。

事件委托是利用事件的冒泡原理来实现的,就是把一个元素响应事件的函数委托到另一个元素,一般是把一组元素的事件委托到他的父元素上。
委托的优点是:减少内存消耗,节约效率,动态绑定事件。

事件代理是利用事件的冒泡原理来实现的,何为事件冒泡呢?
就是事件从最深的节点开始,然后逐步向上传播事件

举个例子:页面上有这么一个节点树,div>ul>li>a;,比如给最里面的 a 加一个 click 点击事件,那么这个事件就会一层一层的往外执行,执行顺序a>li>ul>div,有这样一个机制,那么我们给最外面的 div 加点击事件,那么里面的ul,li,a做点击事件的时候,都会冒泡到最外层的 div 上,所以都会触发,这就是事件代理,代理它们父级代为执行事件。

事件冒泡,就是元素自身的事件被触发后,如果父元素有相同的事件,如onclick事件,那么元素本身的触发状态就会传递,也就是冒到父元素,父元素的相同事件也会一级一级根据嵌套关系向外触发,直到document/window,冒泡过程结束。

18、Eventloop (js运行机制)

在 js 中,任务分为宏任务(macrotask)和微任务(microtask),这两个任务分别维护一个队列,均采用先进先出的策略进行执行。同步执行的任务都在宏任务上执行。

宏任务主要有:script(整体代码)、setTimeout、setInterval、I/O、UI 交互事件、postMessage、MessageChannel、setImmediate(Node.js 环境)。

微任务主要有:Promise.then、 MutationObserver、 process.nextTick(Node.js 环境)。

具体的操作步骤如下:

  1. 从宏任务的头部取出一个任务执行;
  2. 执行过程中若遇到微任务则将其添加到微任务的队列中;
  3. 宏任务执行完毕后,微任务的队列中是否存在任务,若存在,则挨个儿出去执行,直到执行完毕;
  4. GUI 渲染;
  5. 回到步骤 1,直到宏任务执行完毕;

这 4 步构成了一个事件的循环检测机制,即我们所称的eventloop。

  • JavaScript 单线程,任务需要排队执行。
  • 同步任务进入主线程排队,异步任务进入事件队列排队等待被推入主线程执行。
  • 定时器的延迟时间为 0 并不是立刻执行,只是代表相比于其他定时器更早的被执行。
  • 以宏任务和微任务进一步理解js执行机制
  • 整段代码作为宏任务开始执行,执行过程中宏任务和微任务进入相应的队列中。
  • 整段代码执行结束,看微任务队列中是否有任务等待执行,如果有则执行所有的微任务,直到微任务队列中的任务执行完毕,如果没有则继续执行新的宏任务。
  • 执行新的宏任务,凡是在执行宏任务过程中遇到微任务都将其推入微任务队列中执行。
  • 反复如此直到所有任务全部执行完毕。

任务队列中,在每一次事件循环中,macrotask 只会提取一个执行,而microtask 会一直提取,直到 microsoft 队列为空为止。

也就是说如果某个 microtask 任务被推入到执行中,那么当主线程任务执行完成后,会循环调用该队列任务中的下一个任务来执行,直到该任务队列到最后一个任务为止。而事件循环每次只会入栈一个 macrotask,主线程执行完成该任务后又会检查 microtasks 队列并完成里面的所有任务后再执行 macrotask 的任务。

macrotasks(宏任务 task,也是我们常说的任务队列):
setTimeout(延迟调用),setInterval(间歇调用),setImmediate(Node 的立即调用),I/O(I/O 操作),UI rendering(UI 渲染)。

19、let、const、 var的区别 ,什么是块级作用域,如何用ES5的方法实现块级作用域(立即执行函数),ES6 呢

提起这三个最明显的区别是,var 声明的变量是全局或者整个函数块的,而 let,const 声明的变量是块级的变量,var 声明的变量存在变量提升,let,const 不存在,let 声明的变量允许重新赋值,const 不允许。

20、什么是事件监听

addEventListener() 方法,用于向指定元素添加事件句柄,它可以更简单的控制事件,语法为

element.addEventListener(event, function, useCapture);

第一个参数是事件的类型(如 “click” 或 “mousedown”).

第二个参数是事件触发后调用的函数。

第三个参数是个布尔值用于描述事件是冒泡还是捕获。该参数是可选的,默认的是冒泡,即 false,当值为 true 时,即为捕获阶段。

事件传递有两种方式,冒泡和捕获

事件传递定义了元素事件触发的顺序,如果你将 p 元素插入到 div 元素中,用户点击 p元素。

在冒泡中,内部元素先被触发,然后再触发外部元素。

捕获中,外部元素先被触发,在触发内部元素。

21、浅克隆、深刻隆

  • 浅克隆简单来说就是复制,因为引用型变量保存的是内存地址,其实后来操作的都是同一块内存,导致了数组内容都一样。
  • 深克隆就是在克隆的时候判断一下属性的类型是不是引用型变量,如果是的话就用递归方法让它一层一层进去复制自己。

22、浅拷贝、深拷贝

基本数据类型:名字和值都存在栈中。

引用数据类型:名字在栈中,值在堆中,栈内存会提供一个引用地址,指向堆内存中的值。

浅拷贝:1.for只遍历第一层 2.assign 3. =直接赋值
深拷贝:1.递归遍历所有层级
2.利用JSON对象【JSON.stringfy() JSON.parse()
3.通过jQuery的extend方法实现深拷贝
4.lodash函数库实现深拷贝
5.用slice实现对数组的深拷贝,slice() 方法可从已有的数组中返回选定的元素。
6.使用扩展运算符实现深拷贝
7.如对象的value是基本类型,可以用Object.assign来实现深拷贝,但是要把它赋值给一个空对象
assign第一层是深拷贝,第二层以后是浅拷贝
9.用concat实现对数组的深拷贝
10.直接使用var newObj = Object.create(oldObj),可以达到深拷贝的效果。
11.手动实现深拷贝

  • 简单来说,就是一个变量赋值给另一个变量,其中一个变量的值改变,两个变量的值都变了,这就叫做浅拷贝。
  • ES6语法中也给我们提供了一个浅拷贝的方法Object.assign(target, sources)
  • target:拷贝的目标 sources: 被拷贝的对象
  • 浅拷贝, 是拷贝后,新拷贝的对象内部仍然有一部分数据会随着源对象的变化而变化。
  • 深拷贝就是,拷贝后, 新拷贝的对象内部所有数据都是独立存在的,不会随着源对象的改变而改变。
  • 深拷贝的话一共有两种方式: 递归拷贝 和 利用JSON函数深拷贝JSON.parse(JSON.stringify(a))

设计模式:单例,工厂,发布订阅

(1)单例模式: 在它的核心结构中值包含一个被称为单例的特殊类。一个类只有一个实例,即一个类只有一个对象实例。

(2)工厂模式: 在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

(3)发布订阅模式: 在软件架构中,发布订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在。同样的,订阅者可以表达对一个或多个类别的兴趣,只接收感兴趣的消息,无需了解哪些发布者(如果有的话)存在。

说说vue react angularjs jquery的区别

JQuery与另外几者最大的区别是,JQuery是事件驱动,其他两者是数据驱动。

JQuery业务逻辑和UI更改该混在一起, UI里面还参杂这交互逻辑,让本来混乱的逻辑更加混乱。

Angular,vue是双向绑定,而React不是 。

webpack 和 gulp 区别(模块化与流的区别)

(1)gulp 强调的是前端开发的工作流程,我们可以通过配置一系列的task,定义task处理的事务(例如文件压缩合并、雪碧图、启动server、版本控制等),然后定义执行顺序,来让 gulp 执行这些 task,从而构建项目的整个前端开发流程。

(2)webpack 是一个前端模块化方案,更侧重模块打包,我们可以把开发中的所有资源(图片、js文件、css文件等)都看成模块,通过loader(加载器)和 plugins(插件)对资源进行处理,打包成符合生产环境部署的前端资源。

ajax返回的状态

0 - (未初始化)还没有调用send()方法

1 - (载入)已调用send()方法,正在发送请求

2 - (载入完成)send()方法执行完成,已经接收到全部响应内容

3 - (交互)正在解析响应内容

4 - (完成)响应内容解析完成,可以在客户端调用了

实现一个 Ajax (写出原生Ajax)如果我想发出两个有顺序的ajax需要怎么做?

Ajax 能够在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页内容,实现局部刷新,大大降低了资源的浪费,是一门用于快速创建动态网页的技术,ajax 的使用分为四部分:

1、创建 XMLHttpRequest 对象 var xhr = new XMLHttpRequest();

2、向服务器发送请求,使用 XMLHttpRequest 对象的 open 和 send 方法。

3、监听状态变化,执行相应回调函数。

(1)设置请求参数(请求方式,请求页面的相对路径,是否异步)

(2)设置回调函数,一个处理服务器响应的函数,使用 onreadystatechange ,类似函数指针。

(3)获取异步对象的 readyState 属性:该属性存有服务器响应的状态信息。每当 readyState 改变时,onreadystatechange 函数就会被执行。

(4)判断响应报文的状态,若为200说明服务器正常运行并返回响应数据。

(5)读取响应数据,可以通过 responseText 属性来取回由服务器返回的数据。

var xhr = new XMLHttpRequest();
xhr.open('get', 'aabb.php', true);
xhr.send(null);
xhr.onreadystatechange = function() {
	if(xhr.readyState==4 && xhr.status==200) {
		console.log(xhr.responseText);	
	}
}

发出两个有顺序的 ajax,可以用回调函数,也可以使用 Promise.then或者 async 等。

JSONP的缺点

JSON 只支持 get,因为 script 标签只能使用 get 请求;

JSONP 需要后端配合返回指定格式的数据。

跨域(jsonp,ajax)

JSONP:ajax 请求受同源策略影响,不允许进行跨域请求,而 script 标签 src 属性中的链接却可以访问跨域的 js 脚本,利用这个特性,服务端不再返回 JSON 格式的数据,而是返回一段调用某个函数的 js 代码,在 src 中进行了调用,这样实现了跨域。

如何实现跨域

(1)JSONP:通过动态创建 script,再请求一个带参网址实现跨域通信。

(2)document.domain + iframe 跨域:两个页面都通过 js 强制设置document.domain 为基础主域,就实现了同域。

(3)location.hash + iframe跨域:a 欲与 b 跨域相互通信,通过中间页 c 来实现。 三个页面,不同域之间利用 iframe 的 location.hash 传值,相同域之间直接 js 访问来通信。

(4)window.name + iframe跨域:通过 iframe 的 src 属性由外域转向本地域,跨域数据即由 iframe 的 window.name 从外域传递到本地域。

(5)postMessage 跨域:可以跨域操作的 window 属性之一。

(6)CORS:服务端设置 Access-Control-Allow-Origin 即可,前端无须设置,若要带 cookie 请求,前后端都需要设置。

(7)代理跨域:起一个代理服务器,实现数据的转发 。

dom 是什么,你的理解?

文档对象模型(Document Object Model,简称DOM),是 W3C 组织推荐的处理可扩展标志语言的标准编程接口。在网页上,组织页面(或文档)的对象被组织在一个树形结构中,用来表示文档中对象的标准模型就称为 DOM。

简单介绍一下 symbol

Symbol 是 ES6 的新增属性,代表用给定名称作为唯一标识,这种类型的值可以这样创建,let id=symbol(“id”)

Symbol 确保唯一,即使采用相同的名称,也会产生不同的值,我们创建一个字段,仅为知道对应 symbol 的人能访问,使用 symbol 很有用,symbol 并不是 100% 隐藏,有内置方法。

Object.getOwnPropertySymbols(obj) 可以获得所有的 symbol。

也有一个方法 Reflect.ownKeys(obj) 返回对象所有的键,包括 symbol。

所以并不是真正隐藏。但大多数库内置方法和语法结构遵循通用约定他们是隐藏的。

js判断类型

判断方法:typeof(),instanceof,Object.prototype.toString.call()等

如何判断一个数组(讲到typeof差点掉坑里)

Object.prototype.call.toString()
instanceof

数组常用方法

push(),pop(),shift(),unshift(),splice(),sort(),reverse(),map()等

说一下什么是virtual dom

用JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中 当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异 把所记录的差异应用到所构建的真正的DOM树上,视图就更新了。Virtual DOM 本质上就是在 JS 和 DOM 之间做了一个缓存。

webpack用来干什么的

webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle。

写一个函数,第一秒打印1,第二秒打印2

两个方法,第一个是用 let 块级作用域

for(let i=0;i<5;i++){
	setTimeout(function(){
		console.log(i)
	},1000*i)
}

第二个方法闭包

for(var i=0;i<5;i++){
	(function(i){
		setTimeout(function(){
			console.log(i)
		},1000*i)
	})(i)
}

this的指向哪几种

默认绑定:全局环境中,this默认绑定到window。
隐式绑定:一般地,被直接对象所包含的函数调用时,也称为方法调用,this隐式绑定到该直接对象。

隐式丢失:隐式丢失是指被隐式绑定的函数丢失绑定对象,从而默认绑定到window。
显式绑定:通过call()、apply()、bind()方法把对象绑定到this上,叫做显式绑定。

new绑定:如果函数或者方法调用之前带有关键字new,它就构成构造函数调用。对于this绑定来说,称为new绑定。

【1】构造函数通常不使用return关键字,它们通常初始化新对象,当构造函数的函数体执行完毕时,它会显式返回。在这种情况下,构造函数调用表达式的计算结果就是这个新对象的值。

【2】如果构造函数使用return语句但没有指定返回值,或者返回一个原始值,那么这时将忽略返回值,同时使用这个新对象作为调用结果。

【3】如果构造函数显式地使用return语句返回一个对象,那么调用表达式的值就是这个对象。

mouseover和mouseenter的区别

mouseover:当鼠标移入元素或其子元素都会触发事件,所以有一个重复触发,冒泡的过程。对应的移除事件是mouseout 。

mouseenter:当鼠标移除元素本身(不包含元素的子元素)会触发事件,也就是不会冒泡,对应的移除事件是mouseleave。

js的new操作符做了哪些事情

new 操作符新建了一个空对象,这个对象原型指向构造函数的prototype,执行构造函数后返回这个对象。

js的各种位置,比如clientHeight,scrollHeight,offsetHeight ,以及scrollTop, offsetTop,clientTop的区别?

clientHeight:表示的是可视区域的高度,不包含border和滚动条

offsetHeight:表示可视区域的高度,包含了border和滚动条

scrollHeight:表示了所有区域的高度,包含了因为滚动被隐藏的部分。

clientTop:表示边框border的厚度,在未指定的情况下一般为0

scrollTop:滚动后被隐藏的高度,获取对象相对于由
offsetParent 属性指定的父坐标(css定位的元素或body元素)距离顶端的高度。

px rem em vh vw之间的区别

1、px:相对长度单位。像素 px 是相对于显示器屏幕分辨率而言的。

2、em:相对长度单位。相对于当前对象内文本的字体尺寸。如当前对行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸。

3、rem:相对长度单位。r’是“root”的缩写,相对于根元素的字体大小。

4、vh 和 vw:相对于视口的高度和宽度,而不是父元素的(CSS百分比是相对于包含它的最近的父元素的高度和宽度)。

vue 生命周期

vue生命周期是指vue实例对象从创建之初到销毁的过程,vue所有功能的实现都是围绕其生命周期进行的,在生命周期的不同阶段调用对应的钩子函数实现组件数据管理和DOM渲染两大重要功能。

vue生命周期可以分为八个阶段,分别是:
每个周期具体适合哪些场景
	beforeCreate(创建前) :可以在这加个loading事件,在加载实例时触发
	created(创建后):初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用
	beforeMount(载入前)
	mounted(载入后):挂载元素,获取到DOM节点
	beforeUpdate(更新前)
	updated(更新后):如果对数据统一处理,在这里写上相应函数
	beforeDestroy(销毁前):可以做一个确认停止事件的确认框
	destroyed(销毁后)

nextTick : 更新数据后立即操作dom

vue生命周期的作用: 它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。

第一次页面加载会触发哪几个钩子?
第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子。

created 和mounted 的区别
created:在模板渲染成 html 前调用,即通常初始化某些属性值,然后再渲染成视图。

mounted:在模板渲染成 html 后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。

DOM操作:获取、增、删、查、改等操作

创建:
createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点
添加:appendChild()
移出:removeChild()
替换:replaceChild()
插入:insertBefore()
复制:cloneNode(true)
查找:
getElementsByTagName() //通过标签名称
getElementsByClassName() //通过标签名称
getElementsByName() //通过元素的Name属性的值
getElementById() //通过元素Id,唯一性

循环

(1)for:for(let i=0; i<10; i++)  i:下标     arr[i]:值

(2)for…each: arr.forEach((item,index) => {}) 遍历数组,不能使用break,contintue,return

(3)for…in:for (var i in arr){ // i是下标(索引)}
 i:下标 		arr[i]:值 
 原型链上的所有属性都将被访问 arr.hasOwnProperty(i)可以判断是否在实例上,在实例上才会被返回

(4)for…of: 只能遍历数组
(5)map: 有返回值,可以返回结果数组,不能遍历对象,只能遍历数组或对象数组
var arr = [‘星期一’, ‘星期二’, ‘星期三’];
var a = arr.map(function(item){
	console.log(item)
	return item === ‘星期二’
})
console.log(a)

js中的堆和栈

  • 栈(stack):简单地数据段,存放在栈中,有固定大小的内存(自动分配),自动释放。

    • 基本数据类型:number,string,boolean,undefined,null
    • 栈存储了什么:变量名,基本数据类型值,地址
    • 全局作用域,私有作用域,都属是栈内存,理论上,存储的越少,运行速度越快
    • 先进后出
    • 栈内存回收:作用域销毁(立即销毁,不销毁,不立即销毁)
      • 全局作用域销毁:一般情况不销毁,页面关闭,整个作用域销毁
      • 私有作用域销毁 :
        • 不销毁 ;销毁 ;不立即销毁
  • 堆(heap):动态分配内存,大小不定也不会自动释放

    • 引用类型:栈中存放地址,指向堆中的对象,当我们要获取(函数,数组,对象等)的时候,先从栈中获取地址,然后从堆中获取数据

    • 先进先出

    • 堆存储了什么:引用数据类型的值

    • 内存回收:GC垃圾回收机制

      • chrome:标记法,每隔一段时间对所有的空间地址检测,如果没有被占用,立即回收

      • ie和火狐:计数法,空间地址被占用一次+1,空闲一次空间地址-1,如果为0 被回收

computed、methods、watch的区别

(1)methods:调用方法一定要有()。methods方法页面刚加载时调用一次,结果不会缓存。methods里面是用来定义函数的,很显然,它需要手动调用才能执行。而不像 watch 和 computed 那样,“自动执行”预先定义的函数。

(2)computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;

computed:计算属性可以依赖多个 vue 实例的数据,只要其中一个任何一个数据发生变化,计算属性就会重新执行,视图也会更新(有缓存

(3)watch: 是监听,监听是方法,一旦监听的值发生变化,就会调用相应的方法 methods 是必须要有一定触发条件才能执行,(没有缓存)(点击执行)

watch擅长处理的场景:一个数据影响多个数据
computed擅长处理的场景:一个数据受多个数据影响

v-model是什么? vue中标签怎么绑定事件?

答:v-model这个指令只能用在表单元素上,可以用他进行双向数据绑定。绑定事件:<input @click=doLog() />

说出至少4种vue当中的指令和它的用法?

答:v-if:判断是否隐藏;
v-for:数据循环出来;
v-bind:class:绑定一个属性;
v-model:实现双向绑定

请说下 vue 组件的优点,以及注册使用的过程?

答:首先,组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发:效率低、难维护、复用性等问题。

使用Vue.component方法注册组件。子组件需要数据,可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用emit方法。

vuex是什么?怎么使用?哪种功能场景使用它?

答:vue框架中状态管理。在main.js引入store,注入。

新建了一个目录store.js,…… export 。

场景有:单页应用中,组件之间的状态。音乐播放、登录状态、加入购物车

vue-router是什么?它有哪些组件?

vue用来写路由一个插件。router-link、router-view

你是怎么认识vuex的?

答:vuex可以理解为一种状态管理的开发模式或者框架,data中的属性需要共享给其他vue组件使用。状态为state集中放在store中; 改变状态的方式是提交mutations,这是个同步的事物; 异步逻辑应该封装在action中。

vuex有哪几种属性?

答:有五种,分别是 State、 Getter、Mutation 、Action、 Module

state => 基本数据(数据源存放地)
getters => 从基本数据派生出来的数据
mutations => 提交更改数据的方法,同步!
actions => 像一个装饰器,包裹mutations,使之可以异步。
modules => 模块化Vuex

vue-router是什么

Vue Router 是 Vue.js 官方的路由管理器,创建单页应用程序:通过Vue.js,我们已经在使用组件组成应用程序。将Vue Router添加到混合中时,我们要做的就是将组件映射到路由,并让Vue Router知道在哪里渲染它们

vue-router有哪几种导航钩子( 导航守卫 )

1、全局守卫: router.beforeEach
2、全局解析守卫: router.beforeResolve
3、全局后置钩子: router.afterEach
4、路由独享的守卫: beforeEnter
5、组件内的守卫: beforeRouteEnter、beforeRouteUpdate (2.2 新增)、beforeRouteLeave

VueRouter中hash和history模式的原理

hash 模式:在用超链接制作锚点跳转的时候,就会发现,url后面跟了"#id"(略。。。啊格雷),hash值就是url中从"#"号开始到结束的部分。当 URL 改变时,页面不会重新加载。

History 模式 :history就是我们平时看到的正常的连接形式。利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。pushState 设置的新 URL 可以是与当前 URL 同源的任意 URL。
注意一点:history 模式需要后端配合将所有访问都指向index.html,否则用户刷新页面,会导致 404 错误。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-28 21:57:59  更:2021-08-28 21:58:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 5:29:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计