【1】null和undefined的区别
同:
1.都是js的基本类型,保存在栈中,表示“无、没有”的意思。
2.if语句中的null和undefined都是false。
var a = undefined var b = null if (!a) { console.log('undefined is false'); } if (!b) { console.log('null is false'); } a == b //true
异:
1.null表示空值,一个变量将来可能指向一个对象;一个不存在的dom节点就是null,转为数值是0。
undefined表示变量声明但没有赋值或者不存在的对象属性值,转为数值是NaN。
2.典型用法:
null表示"没有对象",即该处不应该有值。典型用法是:
(1) 作为函数的参数,表示该函数的参数不是对象。
(2) 作为对象原型链的终点。
undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。典型用法是:
(1)变量被声明了,但没有赋值时,就等于undefined。
(2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。
(3)对象没有赋值的属性,该属性的值为undefined。
(4)函数没有返回值时,默认返回undefined。
【2】什么是w3c标准?理解下
w3c是万维网联盟标准,它不是指某一个标准,而是指一系列标准的集合。
w3c标准可分为结构、表现、行为,三部分独立为模块化。结构化标准语言主要包括XML和XHTML;表现标准语言主要指CSS;行为标准主要包括对象模型ECMAScript。【jQuery不符合w3c标准】
1.需要声明(DOCTYPE)
2. 需要定义语言编码
<meta http-equiv=“Content-Type” content="text/html" charset="utf-8" />
3.JavaScript定义
js必须要用<script language="javascript" type="text/javascript">来定义开头,而不是原来的<script language="javascript">或干脆直接<script>
4.CSS定义
CSS必须要用<style type=“text/css”>开头来定义,而不是原来的直接<style>;也不建议直接写在内容代码中的行内样式。
5.不要在注释内容中使用’’–’’
“–”只能发生在XHTML注释的开头和结束,也就是说,在内容中不能有-
例如下面的代码是无效的: <!--这里是注释-----------这里是注释--> 正确的应用等号或者空格替换内部的虚线: <!--这里是注释============这里是注释-->
6.所有标签的元素和属性的名字都必须使用小写
与HTML不一样,XHTML对大小写是敏感的,
和是不同的标签7.所有的属性必须用引号""括起来
在HTML中,可以不需要给属性值加引号,但是在XHTML中,它们必须要加引号
例如:<height=80>必须修改为:<height=“80”>、<alt=“say'hello'”>修改为<alt="say'hello'">
8. 把所有特殊符号用编码表示,例如:小于号(<)用<表示。
9.所有属性必须有属性值
XHTML规定所有属性都必须有个值,没有值就是重复本身
// 不规范 <td nowrap><input type="checkbox" name="shirt" value="medium" checked> // 规范做法 <td nowrap="nowrap"><input type="checkbox" name="shirt" value="medium" checked="checked" />
tips:
1、标签规范可以提高搜索引擎对页面的抓取效率,对SEO(搜索引擎优化)很有帮助
2、尽量使用外链css样式表和js脚本:结构、表现和行为分为三块,符合规范,同时提高页面渲染速度,提高用户的体验。
3、样式尽量少用行内样式表,使结构与表现分离,标签的id和class等属性命名要做到见文知义,标签越少,加载越快,用户体验提高,代码维护简单,便于改版
【3】虚拟dom树的理解(参考文章虚拟DOM的实现原理与优缺点_虚拟dom的优缺点_z逍遥的博客-CSDN博客)
虚拟DOM就是为了解决浏览器性能问题而被设计出来的。如前,若一次操作中有10次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地一个JS对象中,最终将这个JS对象一次性attch到DOM树上,再进行后续操作,避免大量无谓的计算量。所以,用JS对象模拟DOM节点的好处是,页面的更新可以先全部反映在JS对象(虚拟DOM)上,操作内存中的JS对象的速度显然要更快,等更新完成后,再将最终的JS对象映射成真实的DOM,交由浏览器去绘制。
虚拟dom本质上是js对象,是对真实dom的抽象。状态变化时,记录新树和旧树的差异,最后把差异更新到真实dom中。
虚拟dom的作用:①解决代码冗余,耦合度高且难维护的问题;②优化前端性能,提高渲染效率。
1.patch函数
patch函数的执行分为两个阶段,两次传递的参数都是两个
第一阶段为虚拟dom的第一次渲染,传递的两个参数分别是放真实DOM的container和生成的vnode,此时patch函数的作用是用来将初次生成的真实DOM结构挂载到指定的container上面。
第二阶段传递的两个参数分别为vnode和newVnode,此时patch函数的作用是使用diff算法对比两个参数的差异,进而更新参数变化的DOM节点;
可以发发现h函数和patch函数在cnabbdom中实现vdom到真实DOM的转化起到了至关重要的作用,那么还有一个很重要的环节,patch函数中是怎么样实现对比两个vnode从而实现对真实DOM的更新的呢,这里还要提一下snabbdom的另外一个核心算法,即diff算法。
2.diff算法
把树形结构按照层级分解,只比较同级元素,不同层级的节点只有创建和删除操作。
3.虚拟dom的优缺点:
优点:
保证性能下限: 虚拟DOM可以经过diff找出最小差异,然后批量进行patch,这种操作虽然比不上手动优化,但是比起粗暴的DOM操作性能要好很多,因此虚拟DOM可以保证性能下限
无需手动操作DOM: 虚拟DOM的diff和patch都是在一次更新中自动进行的,我们无需手动操作DOM,极大提高开发效率
跨平台: 虚拟DOM本质上是JavaScript对象,而DOM与平台强相关,相比之下虚拟DOM可以进行更方便地跨平台操作,例如服务器渲染、移动端开发等等
缺点:
无法进行极致优化: 在一些性能要求极高的应用中虚拟DOM无法进行针对性的极致优化,比如vscode采用直接手动操作DOM的方式进行极端的性能优化。
【4】浏览器内核
1.IE --> Trident内核,也就是俗称的IE内核
2.Chrome --> 以前是Webkit内核,现在是Blink内核
3.Firefox --> Gecko内核
4.Opera -->Blink内核
5.Safari --> Webkit内核
【5】JavaScript的基本规范,写几条
1.变量和函数为小驼峰法标识
2.通常运算符 ( = + - * / ) 前后需要添加空格
3.通常使用 4 个空格符号来缩进代码块
4.一条语句通常以分号作为结束符
5.常量 (如 PI) 为大写
6.为了便于阅读每行字符建议小于数 80 个,如果一个 JavaScript 语句超过了 80 个字符,建议在 运算符或者逗号后换行。
【6】window对象和document对象的区别(参考文章JS中的window对象和document对象是什么?有什么区别?_window对象和document对象的区别_高明懿大可爱的博客-CSDN博客)
一、指代不同
1、document对象:代表给定浏览器窗口中的HTML文档,document是window的一个对象属bai性。
2、window对象:表示浏览器中打开的窗口。
二、作用不同
1、document对象:使用document对象可以对HTML文档进行检查、修改或添加内容,并处理该文档内部的事件。
2、window对象:浏览器会为HTML文档创建一个window对象,并未每个框架创建一个额外的window对象。
三、使用方式不同:
1、document对象:在Web页面上,document对象可通过window对象的document属性引用,或者直接引用。
2、window对象:没有应用于window对象的公开标准,不过所有浏览器都支持该对象。
【7】BOM和DOM的区别(参考文章DOM和BOM的区别_bom和dom的区别_学学学无止境的博客-CSDN博客)
js是三部分组成:
ECMAScript:描述了js的语法和基本对象;
BOM(浏览器对象):与浏览器交互的方法和对象;
DOM(文档对象模型):定义了梳理网页的内容和接口;
DOM是W3C的标准(所有浏览器公共遵守的标准);BOM是各个浏览器厂商根据DOM在各自浏览器上的实现(浏览器不同,具体的表现形式也有差异,ie更是风格迥异)
1.DOM(document也是BOM的window的子对象;)
文档对象模型,它指的是把文档当做一个对象来对待,这个对象主要定义了处理网页的内容和接口。
2.BOM( location、navigato、document)
浏览器对象模型,它指的是把浏览器当做一个对象来对待,这个对象主要定义了浏览器进行交互的方法和接口。
BOM的核心是window,而window具有双重角色,它既是js访问浏览器窗口的一个接口,又是一个全局对象,这就代表网页中定义的任何对象、变量和函数都是作为全局对象的一个属性或方法存在。
【8】document.write和innerHTML的区别(参考文章document.write和innerHTML的区别_innerhtml和document.write区别_小怪兽_v的博客-CSDN博客)
document.write是直接写入到页面的内容流,如果在写之前没有调用document.open, 浏览器会自动调用open。每次写完关闭之后重新调用该函数,会导致页面被重写。
innerHTML则是DOM页面元素的一个属性,代表该元素的html内容。(可获取内容 、修改内容)可以精确到某一个具体的元素来进行更改。
innerHTML很多情况下都优于document.write,其原因在于其允许更精确的控制要刷新页面的那一个部分。
write是方法,会全部重写网页内容。
而innerHTML则是属性,而且是定向改写。
【9】计算属性computed和watch的区别
computed的使用场景:监听其他值的变化,经过逻辑处理得到新属性值,可以监听多个值来完成一个值的计算,例如算出几个数的总和。
watch的使用场景:它可以监听这个值的新值和旧值,然后根据这个值的变化做出逻辑处理,可以监听一个值完成多个计算,例如监听A值改变相应的改变B值和C值。
计算属性computed是依赖其他属性得到一个新属性,基于data中声明过或者父组件传递的 props 中的数据通过计算得到的一个新值,这个新值只会根据已知值的变化而变化,换句话说,这个属性依赖其他属性,由其他属性计算而来的。
特点:
computed,支持缓存,只有依赖数据发生改变,才会重新进行计算(缓存功能:多次调用也不会重新计算)
● computed 不支持异步,当 computed 内有异步操作时无效
● 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一(可以依赖一个或多个属性的值),一般用 computed
● 如果 computed 属性属性值是函数,那么默认会走 get() ;函数的返回值就是属性的属性值;在 computed 中的,属性都有一个 get() 和一个 set(),当数据变化时,调用 set() (computed里属性值变化,调用此属性的set())。
● computed的属性值用法和data、prop相同,且不能与其属性冲突
watch,主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作,可以看作是 computed 和 methods 的结合体;
● 可以监听的数据来源:data,props,computed内的数据;
● watch支持异步;
● 不支持缓存,监听的数据改变,直接会触发相应的操作;
● 监听函数有两个参数,第一个是最新的值,第二个参数是输入之前的值,顺序是新值,旧值,如果只填一个值,则为新值。
【10】父子组件的生命周期(参考文章Vue——父子组件的生命周期(执行顺序)_默默花上开的博客-CSDN博客)
一个组件的生命周期:
- 挂载(初始化相关属性)
- beforeCreate
- created
- beforeMount
- mounted
- 更新(元素或组件的变更操作)
- beforeUpdate
- updated
- 销毁(销毁相关属性)
- beforeDestroy
- destroyed
一个完整的父子组件生命周期:
父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted->父beforeUpdate->子beforeUpdate->子updated->父updated->父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
父:
<template> <div> <input type="text" name="text" id="" v-model="text" /> <button id="destroy" @click="handle">点击</button> <livechidren :text="text"></livechidren> </div> </template> <script> import livechidren from "./livechidren.vue"; export default { components: { livechidren }, data() { return { text: "", }; }, methods: { handle() { this.$destroy(); }, }, beforeCreate() { console.log("父组件————beforeCreate..."); }, created() { console.log("父组件————create..."); }, beforeMount() { console.log("父组件————beforeMount..."); }, mounted() { console.log("父组件————mounted..."); }, beforeUpdate() { console.log("父组件————beforeUpdate..."); }, updated() { console.log("父组件————updated..."); }, beforeDestroy() { console.log("父组件————beforeDestroy..."); }, destroyed() { console.log("父组件————destroyed..."); }, }; </script> <style> #destroy{ width: 80px; height: 30px; border: none; background: rgb(209, 250, 236); } </style>
子:
<template> <div>{{text}}</div> </template> <script> export default { data() { return {}; }, props:{ text: { type: String, } }, beforeCreate() { console.log("子组件————beforeCreate..."); }, created() { console.log("子组件————create..."); }, beforeMount() { console.log("子组件————beforeMount..."); }, mounted() { console.log("子组件————mounted..."); }, beforeUpdate() { console.log("子组件————beforeUpdate..."); }, updated() { console.log("子组件————updated..."); }, beforeDestroy() { console.log("子组件————beforeDestroy..."); }, destroyed() { console.log("子组件————destroyed..."); }, }; </script> <style> </style>
结果如下:
【11】什么是闭包?产生原因?
闭包是指能够读取其它函数内部变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。可以把闭包简单理解成 ‘定义在一个函数内部的函数’。
闭包的产生原因:变量作用域的问题(全局变量和局部变量)
由于变量的作用域的原因,函数内部能读取全局变量,函数外部无法读取函数内部的局部变量,为了在函数外部读取局部变量,所以就有了闭包。
闭包的作用:
1.访问其他函数内部变量
2.让这些变量的值始终保存在内存中,保护变量不被内存回收机制回收
3.避免全局变量被污染 方便调用上下文的局部变量,加强封装性
闭包的缺点:
闭包长期占用内存,内存消耗很大,可能导致内存泄露
【12】防止冒泡
1.event.stopPropagation();
2.return false;
3.时间修饰符.stop
【13】v-if和v-for的优先级
当vue处理指令时,v-for比v-if具有更高的优先级;但是在vue3中,v-if具有比v-for更高的优先级。
注意事项:
1.v-if和v-for同时用在同一个元素上,会带来性能上的浪费,每次渲染都会先循环在进行条件判断。
2.如果避免v-if和v-for同时作用在容一个元素上,可以在元素外面套一层写v-if。
3.可以通过计算属性过滤掉那些不需要显示的项
【14】vue的生命周期有哪些(参考文章⑥ Vue的生命周期_vue生命周期_CRMEB的博客-CSDN博客)
简单来说:在 Vue 从创建实例到最终完全消亡的过程中,会执行一系列的方法,用于对应当前 Vue 的状态,这些方法我们叫它:生命周期钩子!
vm的生命周期:
将要创建-->调用beforeCreate函数;
创建完毕-->调用created函数;
将要挂载-->调用beforeMount函数;
挂载完毕-->调用mounted函数;----重要的钩子
将要更新-->调用beforeUpdate函数;
更新完毕-->调用updated函数;
将要销毁-->调用beforeDestroy函数;----重要的钩子
销毁完毕-->调用destroyed函数;
【15】mvc的理解
MVC所有通信都是单向的,提交一次反馈一次,通信一次相互制约。MVC允许在不改变视图的情况下改变视图对用户输入的响应方式,用户对View的操作交给了Controller处理,在Controller中响应View的事件调用Model的接口对数据进行操作,一旦Model发生变化便通知相关视图进行更新。
视图(View):用户界面。(传送指令到 Controller)
控制器(Controller):业务逻辑(完成业务逻辑后,要求 Model 改变状态)
模型(Model):数据保存(将新的数据发送到 View,用户得到反)
【16】mvvm的理解
mvvm前后端分离:Model用纯js对象表示,View负责显示。ViewModel负责把view和model关联起来,把model的数据同步到view,还负责吧view修改的同步到model。
1.各部分之间的通信,都是双向的。
2.View 与 Model 不发生联系,都通过ViewModel传递。
model:服务器的业务逻辑操作
view:用户界面
ViewModel:核心枢纽
底层v-model的原理是事件绑定和属性绑定,事件绑定不是click,而是v-on:input事件绑定,这是input标准事件。
mvvm中的vm是控制逻辑
【17】mvc和mvvm的区别
1.MVC是单向的,而MVVM是双向的,并且是自动的,也就是数据发生变化自动同步视图,视图发生变化自动同步数据。
2.解决了 MVC 中大量的 DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验等问题。
3.在数据频繁更新的时候,采用了虚拟DOM,减少过度渲染,提高性能。