typeof 会返回一个变量的基本类型,instanceof返回的是一个布尔值
instanceof 可以准确的判断复杂引用数据类型,但是不能正确判断基础数据类型
而typeof 也存在弊端,它虽然可以判断基础数据类型(null除外),但是在引用数据类型中,除了Function类型以外,其他的也无法判断
如果需要检测数据类型的话,可以通过Object.prototype.toString,调用该方法,统一返回格式“[object XXX]”字符串
Object.prototype.toString({}) // "[object Object]"
Object.prototype.toString.call({}) // 同上结果,加上call也ok
Object.prototype.toString.call(1) // "[object Number]"
Object.prototype.toString.call('1') // "[object String]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(function(){}) // "[object Function]"
Object.prototype.toString.call(null) //"[object Null]"
Object.prototype.toString.call(undefined) //"[object Undefined]"
Object.prototype.toString.call(/123/g) //"[object RegExp]"
Object.prototype.toString.call(new Date()) //"[object Date]"
Object.prototype.toString.call([]) //"[object Array]"
Object.prototype.toString.call(document) //"[object HTMLDocument]"
Object.prototype.toString.call(window) //"[object Window
作用域即变量和函数生效的区域的集合,换句话说,作用域决定了代码区块中变量和其他资源的可见性。
我们一般讲作用域分为:全局作用域,函数作用域,块级作用域。
任何不在函数中或者大括号中声明的变量,都是在全局作用域下,全局作用域下声明的变量可以在程序的任意位置访问
函数作用域也叫局部作用域,如果一个变量是在函数内部声明的它就在一个函数作用域下。这些变量也只能在函数内部访问,不能在函数外访问
ES6引进了let 和const关键字,和var关键字不同,在大括号中使用let和const声明的变量存在于块级作用域中。在大括号外不能访问这些变量。
词法作用域 又叫静态作用域,变量被创建好时就确定好了,而非执行阶段确定的。也就是说我们写好代码时它的作用域就确定了,JavaScript 遵循的就是词法作用域。
当在JavaScript中使用一个变量的时候,首先JavaScript引擎会尝试在当前作用域下去寻找该变量,如果没找到,在到它的上层作用域寻找,以此类推直到找到该变量或是已经到了全局作用域下
如果在全局作用域里仍然找不到该变量,它就会在全局范围内进行隐式声明该变量(非严格模式下)或是直接报错。
浅拷贝指的是创建新的的数据,这个数据有着原始数据属性的一份精确拷贝。
如果属性是基础类型,拷贝的就是基础类型的值。如果属性是引用类型,拷贝的就是内存地址。
即浅拷贝是拷贝一层,深层次的引用类型则共享内存地址。
//浅拷贝
function Clone(obj){
const newObj = {};
for(let prop in obj){
newObj[prop] = obj[prop];
}
return newObj
}
深拷贝开辟一个新的栈,两个对象的属性完全相同,但是对应两个不同的地址,修改一个对象的属性时不会修改类外一个。
function deepClone(obj) {
function isObject(obj) {
return typeof obj === 'object' && typeof obj !== "null"
}
if (!isObject(obj)) {
throw new Error("输入参数不是对象")
}
let res = Array.isArray(obj) ? [...obj] : { ...obj };
Object.keys(res).forEach((item) => {
res[item] = isObject(res[item]) ? deepClone(res[item]) : res[item]
})
return res
}
浅拷贝和深拷贝都创建出一个新的对象,但是在复制对象属性时,浅拷贝只会复制属性指向某个对象的指针,而不是复制对象本身,新旧对象还是共享一块内存,修改对象属性会影响原对象,
而深拷贝会另外创建一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象,是新开劈一个栈空间
JavaScript每个对象都拥有一个原型对象,当去访问一个对象的属性时,它不仅仅在该对象上查找,还会搜寻对象的原型,以及该对象的原型的原型,依次层层向上搜寻,直到找到一个名字匹配的原型或者达到原型链的末尾
每个对象都可以有一个原型_proto_,这个原型还可以有它自己的原型,以此类推,形成一个原型链。查找特定属性的时候,我们先去这个对象里去找,如果没有的话就去它的原型对象里面去,如果还是没有的话再去向原型对象的原型对象里去寻找… 这个操作被委托在整个原型链上,这个就是我们说的原型链了。
一个函数和对其周围状态的引用捆绑在一起,这样的组合就叫闭包,也就是闭包让我们可以在一个内层函数中访问到其外层的作用域。
任何闭包的使用场景都离不开两点
函数的this关键字在JavaScript中的变现略有不同,在绝大多数情况下,函数的调用方式决定了this的值。
this关键字是函数运行时自动生成的一个内部对象,只能在函数内部使用,总指向调用他的对象。
在全局函数中 this指向了window
在事件函数中 this指向了 事件对象
在对象的方法中 this指向了方法调用者
在构造函数中 this指向new 关键字创建的实例对象
在ES6的箭头函数中 this会在编译时绑定,首先箭头函数会从它的父级作用域下找,如果父级作用域还是箭头函数,在往上找,如此直到找到this的指向
执行上下文是对JavaScript代码执行环境的一种抽象的概念,只要有JavaScript代码在运行,那么它就一定是运行在执行上下文中。
执行上下文的类型分为三种:
全局执行上下文:只有一个,浏览器中全局对象就是window对象,this指向了这个全局对象。
函数执行上下文:存在无数个,只有在函数被调用时候才会被创建,每次调用函数都会创建一个新的执行上下文。
Eavl 函数执行上下文:值得是运行在Eavl函数中的代码,很少且不建议使用。
本质上是优化高频率执行代码的一种手段
他们的定义是:
function thorttled(fn,delay = 500){
let timer = null;
let starttime = Date.now();
return function(){
let curTime = Date.now()//当前时间
let remaining = delay - (curTime - startime) //从上一次到现在,还剩下多少多余时间
//这时后this的指向是事件对象
let context = this
//args里面装的是事件对象的参数 事件对象e
let args = arguments;
//触发事件时 先清除一次定时器
clerTimeout(timer)
//判断事件是否该执行了
if(remainig <= 0){
//调用apply立即执行 (不传参也可以实现)
fn.apply(context,args)
//重置事件
starttime= Date.now()
}else{
//如果不用立即执行 那么等待剩余的时间在执行
timer = setTimeout(fn,remaining)
}
}
}
function Shake(fn,delay = 500){
let timer = null;
return function(...args){
//判断延时器是否开启了
if(!timer){
timer = setTimeout(()=>{
//如果第一次进来 调用传进来的fn函数
fn.apply(this,args)
//清空定时器
tiemr = null
// 延时时间
},delay)
}
}
}
继承是面向对象软件技术当中的一个概念。
继承可以使子类具有父类的各种属性和方法,而不需要再次编写同样的代码,在子类继承父类别的同时,可以重新定义某些属性和方法,使其获得与父类不同的功能。
JavaScript常见的继承方式:
原型链继承: 两个实例使用的是一个原型对象,内存空间是共享的。
构造函数继承存在着 :父类原型对象中一旦存在父类之前自己定义的方法,那么子类将无法继承这些方法。
组合继承则是将原型继承 和构造函数继承组合起来。
事件代理 就是把一个元素响应事件的函数委托到另一个元素。事件代理,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,而不是目标元素。当事件响应到目标元素上时,会通过事件冒泡机制从而触发它的外层元素的绑定事件,然后在外层元素上去执行函数。
事件流都会经历三个阶段 捕获阶段——目标阶段——冒泡阶段
javascript从诞生之日起就是一门 单线程的 非阻塞的 脚本语言,单线程意味着,javascript代码在执行的任何时候,都只有一个主线程来处理所有的任务,非阻塞靠的就是 event loop(事件循环)
js的任务队列分为同步任务和异步任务,所有的同步任务都是在主线程里执行的,异步任务可能会在macrotask或者microtask里面
setTimeout、setInterval、setImmediate、I/O、UI rendering
promise.then、process.nextTick
1、先执行主线程
2、遇到宏队列(macrotask)放到宏队列(macrotask)
3、遇到微队列(microtask)放到微队列(microtask)
4、主线程执行完毕
5、执行微队列(microtask),微队列(microtask)执行完毕
6、执行一次宏队列(macrotask)中的一个任务,执行完毕
7、执行微队列(microtask),执行完毕
8、依次循环。。。
事件循环 :在JavaScript中所有任务可以分为同步任务,和异步任务,同步任务进入主线程,宏任务和微任务进入任务队列,主线程的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行,这就是事件循环
一个需要异步执行的代码的函数,执行时机是在主函数执行结束之后,当前宏任务结束之前:
常见的微任务:
Promise
proxy
宏任务的时间粒度比较大,执行的时间间隔是不能精确控制的
常见宏任务:
script
setTimeout/setInterval
执行一个宏任务,如果遇到微任务就将它放到微任务的时间队列中。
当前宏任务执行完毕后,会查看微任务的事件队列,然后将里面的所有微任务依次执行完
Promise 是ES6新增的语法 是异步编程的一个解决方案,将异步操作以同步的操作流程表达出来,避免以前使用回调函数带来的回调地狱的问题,
Promise 是一个构造函数,我们可以通过该构造函数来生成Promise的实例。
Promise有三个状态:pending (等待) fulfilled(成功)rejected(失败)
Promise常用的方法有: .then() .catch .all .race
在ES5中,顶层对象和全局变量是等价的,用var声明的变量即是全局变量,也是顶层变量;
(顶层对象:在浏览器环境下指的是window,在node指的是globar对象)
使用var声明的变量存在变量提升的情况。
var 可以对一个变量进行多次声明,后面的变量会覆盖掉前面的变量。
let 是__ES6__新增的命令,用来声明变量。
用法类似于var,但是let所声明的变量,只在let命令所在的代码块内有效。
let 不存在变量提升,只要块级作用域内存在let 命令,这个区域就不再受外部影响,
使用let声明变量前,该变量都不可用,也就是我们说的暂时性死区。
let 不允许相同作用域下的重复声明。
const 声明一个只读的常量,一旦声明常量的值就不可改变,也就是说const一旦声明,就必须立即初始化。
如果之前使用过var 或 let 声明过变量,就不能在用const声明。
const 实际上并不是变量的值不能改动,而是变量所指向的内存地址不得改动。
对于简单数据的数据,值就保存在变量指向的地址,因此等同于常量。
对于复杂数据类型来说,变量指向的内存地址,保存的只是一个指向实际数据的指针,cosnt可以保证这个指针是固定的,并不能确保该变量的结构不变。其他情况const与let一致。
var 不存在暂时性死区。let, const存在暂时性死区。
var不存在块级作用域,let,const存在块级作用域。
var 可以重复声明,let,const在同一作用域下不允许重复声明。
var 和let 可以修改声明的变量,const 声明一个只读的常量,一旦声明,常量的值就不可改变。
ES6新增了扩展运算符… 可以将一个数组转为用逗号分隔参数序列。
它可以将某些数据结构转换为数组 比如伪数组
可以用于数组间的合并
能够实现简单的数组复刻,但是扩展运算符实现的是浅拷贝,修改了引用指向的值,会同步反应给新数组。
Set是一种叫做集合的数据结构,Map是一种叫做字典的数据结构。
集合:就是由一堆无序的,相关联的,且不重复的内存结构组成的组合。
字典 :是一些元素的集合。每个元素都有一个称作key的域,不同元素的key各不相同。
Vue 的单向数据流:指数据一般从父组件传到子组件,子组件没有权利直接修改父组件传来的数据,即子组件从 props 中直接获取的数据,只能请求父组件修改数据再传给子组件。父级属性值的更新会下行流动到子组件中。
computed适合处理的场景是,一个数据属性在它所依赖的属性发生变化时,也要发生变化,这种情况下,我们最好使用计算属性,computed是带缓存的,只有其引用的响应式属性发生改变时才会重新计算
不支持异步,当computed内有异步操作时无效,无法监听数据的变化
watch更多得是观察的作用,无缓存性,类似于某些数据的监听回调,每当监听的数据变化时都会执行回调进行后续操作。
运用场景:
计算属性: 当我们需要进行数值计算,并且依赖于其他数据时,应该使用computed,因为可以利用computed的缓存特性,避免每次获取值时,都要重新计算。
侦听器: 当我们需要在数据变化时执行异步或者开销较大的操作时,应该使用watch,因为watch选项允许我们执行异步操作,限制我们执行该操作的频率,并在我们得到最终结果前,设置中间件状态。这些都是计算属性无法做到的。
多个因素响应一个显示使用computed ;一个元素变化响应多个其他因素 显示 使用watch
methods使用时,一般情况需要加括号,而computed则不需要。
methods每次调用时会重新执行函数,而computed在其内部变量不变或其返回值不变的情况下多次调用只会执行一次,后续执行时直接从缓存中获取该computed的结果。
由于 JavaScript 的限制,当你利用索引直接设置一个数组或当你修改数组的长度时 Vue检测不到。
全局前置守卫:router.beforeEach
全局解析守卫:router.beforeRsolve
全局后置钩子:router.afterEach 后置钩子没有next参数也不会改变导航本身
路由独享守卫:beforeEnter 路由独享守卫 可以直接路由配置上定义,路由独享守卫只在进入路由时触发。
组件内的守卫:beforeRouteEnter 在渲染该组件的对应路由被验证前触发,不能获取实例this,因为守卫执行时,组件实例还未被创建。
beforeRouteUptate:在当前路由改变,组件被复用时调用。可以访问this,因为组件实例已经挂载完毕。
beforeRouteLeave:在导航离开渲染该组件的对应路由时调用
新增文件的命令:git add file或者git add .
提交文件的命令:git commit –m或者git commit –a
查看工作区状况:git status –s
拉取合并远程分支的操作:git fetch/git merge或者git pull
查看提交记录命令:git reflog
a. 请求数量:合并脚本和样式表,CSS Sprites,拆分初始化负载,划分主域
b. 请求带宽:开启GZip,精简JavaScript,移除重复脚本,图像优化,将icon做成字体
c. 缓存利用:使用CDN,使用外部JavaScript和CSS,添加Expires头,减少DNS查找,配置ETag,使AjaX可缓存
d. 页面结构:将样式表放在顶部,将脚本放在底部,尽早刷新文档的输出
e. 代码校验:避免CSS表达式,避免重定向
BFC全称是Block Formatting Context,即块格式化上下文。它是CSS2.1规范定义的,关于CSS渲染定位的一个概念。
BFC是页面CSS 视觉渲染的一部分,用于决定块盒子的布局及浮动相互影响范围的一个区域。
BFC的一个最重要的效果是,让处于BFC内部的元素与外部的元素相互隔离,使内外元素的定位不会相互影响。
利用BFC可以闭合浮动,防止与浮动元素重叠。
a. 尽量减少页面中重复的HTTP请求数量
b. 服务器开启gzip压缩
减少dom元素数量
避免重定向
使用cdn
c. css样式的定义放置在文件头部
d. Javascript脚本放在文件末尾
e. 压缩合并Javascript、CSS代码
f. 使用多域名负载网页内的多个文件、图片
资源预加载是一个性能优化技术,我们可以使用该技术来预先告知浏览器某些资源可能在将来会被使用到。预加载简单来说就是将所有所需的资源提前请求加载到本地,这样后面在需要用到时就直接从缓存取资源。
//myPreload.js文件
var image= new Image()
image.src="http://pic26.nipic.com/20121213/6168183 004444903000 2.jpg"
懒加载也就是延迟加载。
当访问一个页面的时候,先把img元素或是其他元素的背景图片路径替换成一张大小为1*1px图片的路径(这样就只需请求一次,俗称占位图),只有当图片出现在浏览器的可视区域内时,才设置图片正真的路径,让图片显示出来。这就是图片懒加载。
页面中的img元素,如果没有src属性,浏览器就不会发出请求去下载图片,只有通过javascript设置了图片路径,浏览器才会发送请求。
懒加载的原理就是先在页面中把所有的图片统一使用一张占位图进行占位,把正真的路径存在元素的“data-url”(这个名字起个自己认识好记的就行)属性里,要用的时候就取出来,再设置;
2)区别:
两种技术的本质:两者的行为是相反的,一个是提前加载,一个是迟缓甚至不加载。懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端压力。
一、父组件向子组件传递数据
在 Vue 中,可以使用 props 向子组件传递数据。
二、子组件向父组件传递数据
子组件主要通过事件传递数据给父组件
三、非父子组件传递数据
非父子组件间传值有两种方法,一种是vuex共享数据,
另一种是Bus
因为Vuex里的数据是保存在内存中的,这就面临一个问题:页面一刷新,内存就清空,导致当前页面恢复到原来的样子。
那么怎么让数据长久的保存呢?我们可以把数据保存在localstorage中,
【1】flex弹性盒子
display: flex;
flex: 1;
即可组件中的data
写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data
,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使得所有组件实例共用了一份data
,就会造成一个变了全都会变的结果。
vue中的methods不可以使用箭头函数,因为this指向的不是vue实例,使用箭头函数打印this,发现是undefined
1.云储存
常见的 七牛云,OSS(阿里云)等,这些云平台提供API接口,调用相应的接口,文件上传后会返回图片存储在服务器上的路径,前端获得这个路径保存下来提交给后端即可。此流程处理相对简单。
主要步骤
向后端发送请求,获取OSS配置数据
文件上传,调用OSS提供接口
文件上传完成,后的文件存储在服务器上的路径
将返回的路径存值到表单对象中
在下次 DOM
更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM
。
1.MVVM 即 Model-View-ViewModel 的简写。即模型-视图-视图模型。
2.模型(Model) 指的是后端传递的数据。
3.视图(View)指的是所看到的页面。
4.视图模型(ViewModel)是 mvvm 模式的核心,它是连接 view 和 model 的桥梁。它有两个方向:
一是将模型(Model)转化成视图 (View),即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。
二是将视图 (View)转化成模型(Model),即将所看到的页面转化成后端的数据。实现的方式是:DOM 事件 监听。这两个方向都实现的,我们称之为数据的双向绑定。
diff算法就是用JavaScript来表示一个dom树的结构
然后用这个dom去构建一个真实的dom 插入到文档中
当状态变更的时候 重新构造一个dom树 比较新旧dom树 记录两个dom树的差异 并且通知视图开始更新
diff算法就 用来比较vdom结构的
它是一个object对象模型 用来模拟真实的dom
作用是高效的渲染页面 减少不必要的dom操作 提高渲染效率
说一个b端项目 就可以
当我们使用路由渲染列表时,页面中去调用menu菜单来进行页面渲染出现了问题 ,在menu菜单中我们使用的是import导入组件 设置路由菜单的component 属性,然后在页面引用该菜单时,父级路由的component变成了 undefined ,在想了很多种办法后,多次尝试,把import引入改成懒加载引入即可解决。原理可能是因为 menu中引入了 layout组件 ,layout组建中又引入了menu菜单而导致的。
程序中已动态分配的堆内存由于某种原因程序未释放或者无法释放引发的各种问题。
会运行变慢,崩溃,延迟大等。
js的垃圾回收机制就是为了防止内存泄露的,垃圾回收机制就是间歇的不定期的寻找到不再使用的变量,并释放掉他们所指向的内存。
用transform 代替 top,left ,margin-top, margin-left… 这些位移属性
不要使用 js 代码对dom 元素设置多条样式,选择用一个 className 代替之
不要在循环内获取dom 的样式例如:offsetWidth, offsetHeight, clientWidth, clientHeight等。浏览器有一个回流的缓冲机制,获取这些属性时会产生回流
避免设置多层内联样式,写个外部类这样只回流一次
让多次回流的元素脱离文档流比如动画,使用 position 属性的 fixed 值或 absolute 值
一起变化(同时修改所有需要变化的属性)
他们的区别很大:
回流必将引起重绘,而重绘不一定会引起回流。比如:只有颜色改变的时候就只会发生重绘而不会引起回流
当页面布局和几何属性改变时就需要回流
attribute和是dom元素在文档中作为html标签拥有的属性
propetry是dom元素在js作为对象拥有的属性
对于html的标准属性来说,attribute和property是同步的,是会自动更新的。
但是对于自定义属性来说,他们是不同步的。
map:遍历数组,返回回调返回值组成的新数组。
forEach:遍历数组,无法break,可以用抛出错误来停止
filter:过滤数组
some:遍历数组,有一项返回true,则整体为true
every:有一项返回false,则整体都是false
join:通过指定连接符生成字符串
sort:数组排序
push:末尾添加元素
reverse:反转数组
面向对象的就是使用对象,类,继承,封装等基本概念进行程序设计,
它易维护,易扩展,开发工作的重用性,继承性高,降低重复工作量。
缩短了开发周期。
单台服务器共同协作,不让其中莫一台或者几台超额工作,发挥服务器的最大作用。
http重定向负载均衡:调度者根据策略选择服务器以302响应请求,缺点只有第一次有效果,后续操作维持在该服务器的dns负载均衡:解析域名时,访问多个ip服务器中的一个 。 避免dom渲染的冲突
反向代理负载均衡:访问统一的服务器,由服务器进行调度访问实际的某个服务器,对统一的服务器要求大,性能收到服务器群的数量
Nginx是一款高性能的http 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。
基本操作指令:
启动服务:start nginx
完整有序停止:nginx -s quit
强制关闭:nginx -s stop
重载服务:nginx -s reload (修改配置文件之后,需要重启加载,服务不会中止)
验证配置文件:nginx -t
打开日志文件:nginx -s reopen
使用帮助:nginx -h
vue文件的一个加载器,将template/js/style转换为js模块
用途:js可以写es6,style样式
每个Vue 实例被创建时都要经过一系列的初始化过程,例如需要设置数据监听、编译模板、将实例挂载到DOM并在数据变化时更新DOM等,同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己代码的机会。
beforeCreate created beforeMount mounted
created beforeMount mounted
指令本质上是装饰器,是vue对html元素的扩展,给html元素添加自定义功能。vue编译dom时,会找到指令对象,执行指令相关方法。
自定义指令有五个声明周期
Vue的声明周期钩子核心实现是利用发布订阅模式先把用户传入的生命周期钩子订阅好(内部采用数组的方法存储)然后在创建组件实例的过程中会一次执行对应的钩子方法;
MVC全名是 Model View Controller,即模型-视图-控制器,一种软件设计典范
模型:指的是后端传递的数据。
视图:视图(View)指的是所看到的页面。
控制器:是应用程序处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并像模型发送数据。
首先产品写需求文档 对需求评估 如果需求复杂的话就要写一个技术文档 沟通一下
项目规划 PM会对任务进行分配一下
然后就是ui画图 ue设计
然后我们前段 对着原型图开发 开发前跟后端联调跟他们讲要什么接口 接口什么样子的要么就后端给一个接口文档
测试 我们前端跟测 没问题就上线 上线前给产品看一下 产品觉得没问题就上线
SPA 仅在Web页面初始化时加载对应的HTML,JavaScript,和Css
一旦页面加载完成,SPA不会因为用户的操作而进行页面的重新加载或跳转
而页面的变化时利用路由机制实现HTML内容的变换,避免页面的重新加载
优点:用户体验好,内容改变使用的是局部刷新,避免了不必要的跳转和重复渲染
减轻了服务器的压力,前后端职责分离,架构清晰。
缺点:初次加载耗时多,不利于搜索引擎检索,在SEO上有天然的弱势。
实现mvvm的数据双向绑定,是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来给各个属性添加setter,getter并劫持监听,在数据变动时发布消息给订阅者,触发相应的监听回调。就必须要实现以下几点:
1、实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
2、实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
3、实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图
Vue 的异步更新机制的核心是利用了浏览器的异步任务队列来实现的,首选微任务队列,宏任务队列次之。
大小端存储的理解有两点
1 是针对字节而言. 从字节高位到低位是大端,反之是小端. 一个字节里面的八位不会改变顺序
2 大端小端指的是内存中字节存储的顺序.
cookie对象的domain属性设置了cookie的作用域。domain本身以及domain的子域名可以访问到相关cookie。
允许cookie跨域"Access-Control-Allow-Credentials", “true” 前端设置 withCredentials: true 前端代码
get:请求URL标志的文档 获取信息而非修改信息,get请求一般不产生副作用
post向服务器发送数据
get传送的数据量较小,不能大于2KB;post传送的数据较大,默认不受限制,但实际为80/100KB
GET产生一个TCP数据包;POST产生两个TCP数据包。
强缓存
服务器通过设置http中的header的Expires和cach-control字段告诉浏览器缓存的有效期
协商缓存
简单地说,协商缓存就是通过服务器来判断缓存是否可用。
在 JavaScript 中 null 表示 “什么都没有”。
在 JavaScript 中, undefined 是一个没有设置值的变量。
null 和 undefined 的值相等,但类型不等:
1、CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用
2、CommonJS 模块是运行时加载,ES6 模块是编译时输出接口
发布者订阅者模式其实就是一种对象间一对多的依赖关系(利用消息队列),
当一个对象的状态发生改变时,所有依赖于他的对象都会得到状态改变的通知,
订阅者把自己想订阅的事件注册到调度中心,当发布者发布该事件时到调度中心,也就是事件触发时,由调度中心统一调度订阅者注册到调度中心的代码
定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。
虽然两种模式都存在订阅者和发布者(具体观察者可认为是订阅者、具体目标可认为是发布者) 都相同,但是观察者模式是由具体目标调度的,而发布/订阅模式是统一由调度中心调的,所以观察者模式的订阅者与发布者之间是存在依赖的,而发布/订阅模式则不会。
两种模式都可以用于松散耦合,改进代码管理和潜在的复用。
事件冒泡是由IE开发团队提出来的,即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播。
事件捕获是先由最上一级的节点先接收事件,然后向下传播到具体的节点。
(ES6 新增数据类型)
Symbol 本质上是一种唯一标识符,可用作对象的唯一属性名,这样其他人就不会改写或覆盖你设置的属性值
Symbol 数据类型的特点是唯一性,即使是用同一个变量生成的值也不相等。
Symbol 数据类型的另一特点是隐藏性,for···in,object.keys() 不能访问
但是也有能够访问的方法:Object.getOwnPropertySymbols
(ES6 新增数据类型)
BigInt 是一种特殊的数字类型,它提供了对任意长度整数的支持。
创建 bigint 的方式有两种:在一个整数字面量后面加 n 或者调用 BigInt 函数。
函数副作用 指当调用函数时,除了返回函数值之外,还对主调用函数产生附加的影响。例如修改全局变量(函数外的变量)或修改参数。
函数副作用会给程序设计带来不必要的麻烦,给程序带来十分难以查找的错误,并且降低程序的可读性。严格的函数式语言要求函数必须无副作用。
与之相反。 隐式(Implicit)的意思是,函数通过参数和返回值以外的渠道,和外界进行数据交换。比如读取/修改全局变量,都叫作以隐式的方式和外界进行数据交换。
引用透明 ( Referential Transparent )
引用透明的概念与函数的副作用相关,且受其影响。 如果程序中两个相同值得表达式能在该程序的任何地方互相替换,而不影响程序的动作,那么该程序就具有引用透明性。它的优点是比非引用透明的语言的语义更容易理解,不那么晦涩。纯函数式语言没有变量,所以它们都具有引用透明性。
浏览器通过向 DNS 服务器发送域名,DNS 服务器查询到与域名相对应的 IP 地址,然后返回给浏览器,浏览器再将 IP 地址打在协议上,同时请求参数也会在协议搭载,然后一并发送给对应的服务器。
这应该是最常见的 POST 提交数据的方式了。浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。
使用表单上传文件时,必须让 form 的 enctyped 等于这个值。
这种类型是我们推荐的,。实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。