v-model语法糖是怎么实现的
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> <!-- v-model 只是语法糖而已 --> <!-- v-model 在外部为不同的输出元素应用不同的property并抛出不同的事件 --> <!-- text和textarea 元素应用value property 和 input事件 --> <!-- checkbox 和radio应用checked property 和 change事件--> <!-- select 字段将value 作为prop 并将change 作为事件 --> <!-- 留神:对于须要应用输入法(如中文、日文、韩文等)的语言,你将会发现v-model不会再输入法 组合文字过程中失去更新 --> <!-- 再一般标签上 --> <input v-model="sth" /> //这一行等于下一行 <input v-bind:value="sth" v-on:input="sth = $event.target.value" /> <!-- 再组件上 --> <currency-input v-model="price"></currentcy-input> <!--上行代码是上行的语法糖 <currency-input :value="price" @input="price = arguments[0]"></currency-input> --> <!-- 子组件定义 --> Vue.component('currency-input', { template: ` <span> <input ref="input" :value="value" @input="$emit('input', $event.target.value)" > </span> `, props: ['value'], }) </body></html>
数字证书是什么?
当初的办法也不肯定是平安的,因为没有方法确定失去的公钥就肯定是平安的公钥。可能存在一个中间人,截取了对方发给咱们的公钥,而后将他本人的公钥发送给咱们,当咱们应用他的公钥加密后发送的信息,就能够被他用本人的私钥解密。而后他伪装成咱们以同样的办法向对方发送信息,这样咱们的信息就被窃取了,然而本人还不晓得。为了解决这样的问题,能够应用数字证书。
首先应用一种 Hash 算法来对公钥和其余信息进行加密,生成一个信息摘要,而后让有公信力的认证核心(简称 CA )用它的私钥对音讯摘要加密,造成签名。最初将原始的信息和签名合在一起,称为数字证书。当接管方收到数字证书的时候,先依据原始信息应用同样的 Hash 算法生成一个摘要,而后应用公证处的公钥来对数字证书中的摘要进行解密,最初将解密的摘要和生成的摘要进行比照,就能发现失去的信息是否被更改了。
这个办法最要的是认证核心的可靠性,个别浏览器里会内置一些顶层的认证核心的证书,相当于咱们主动信赖了他们,只有这样能力保证数据的平安。
其余值到布尔类型的值的转换规则?
以下这些是假值:
• undefined
• null
• false
• +0、-0 和 NaN
• ""
假值的布尔强制类型转换后果为 false。从逻辑上说,假值列表以外的都应该是真值。
intanceof 操作符的实现原理及实现
instanceof 运算符用于判断构造函数的 prototype 属性是否呈现在对象的原型链中的任何地位。
function myInstanceof(left, right) { // 获取对象的原型 let proto = Object.getPrototypeOf(left) // 获取构造函数的 prototype 对象 let prototype = right.prototype; // 判断构造函数的 prototype 对象是否在对象的原型链上 while (true) { if (!proto) return false; if (proto === prototype) return true; // 如果没有找到,就持续从其原型上找,Object.getPrototypeOf办法用来获取指定对象的原型 proto = Object.getPrototypeOf(proto); }}
参考:前端进阶面试题具体解答
当在浏览器中输出 Google.com 并且按下回车之后产生了什么?
(1)解析URL: 首先会对 URL 进行解析,剖析所须要应用的传输协定和申请的资源的门路。如果输出的 URL 中的协定或者主机名不非法,将会把地址栏中输出的内容传递给搜索引擎。如果没有问题,浏览器会查看 URL 中是否呈现了非法字符,如果存在非法字符,则对非法字符进行本义后再进行下一过程。
(2)缓存判断: 浏览器会判断所申请的资源是否在缓存里,如果申请的资源在缓存里并且没有生效,那么就间接应用,否则向服务器发动新的申请。
(3)DNS解析: 下一步首先须要获取的是输出的 URL 中的域名的 IP 地址,首先会判断本地是否有该域名的 IP 地址的缓存,如果有则应用,如果没有则向本地 DNS 服务器发动申请。本地 DNS 服务器也会先查看是否存在缓存,如果没有就会先向根域名服务器发动申请,取得负责的顶级域名服务器的地址后,再向顶级域名服务器申请,而后取得负责的权威域名服务器的地址后,再向权威域名服务器发动申请,最终取得域名的 IP 地址后,本地 DNS 服务器再将这个 IP 地址返回给申请的用户。用户向本地 DNS 服务器发动申请属于递归申请,本地 DNS 服务器向各级域名服务器发动申请属于迭代申请。
(4)获取MAC地址: 当浏览器失去 IP 地址后,数据传输还须要晓得目标主机 MAC 地址,因为应用层下发数据给传输层,TCP 协定会指定源端口号和目标端口号,而后下发给网络层。网络层会将本机地址作为源地址,获取的 IP 地址作为目标地址。而后将下发给数据链路层,数据链路层的发送须要退出通信单方的 MAC 地址,本机的 MAC 地址作为源 MAC 地址,目标 MAC 地址须要分状况解决。通过将 IP 地址与本机的子网掩码相与,能够判断是否与申请主机在同一个子网里,如果在同一个子网里,能够应用 APR 协定获取到目标主机的 MAC 地址,如果不在一个子网里,那么申请应该转发给网关,由它代为转发,此时同样能够通过 ARP 协定来获取网关的 MAC 地址,此时目标主机的 MAC 地址应该为网关的地址。
(5)TCP三次握手: 上面是 TCP 建设连贯的三次握手的过程,首先客户端向服务器发送一个 SYN 连贯申请报文段和一个随机序号,服务端接管到申请后向服务器端发送一个 SYN ACK报文段,确认连贯申请,并且也向客户端发送一个随机序号。客户端接管服务器的确认应答后,进入连贯建设的状态,同时向服务器也发送一个ACK 确认报文段,服务器端接管到确认后,也进入连贯建设状态,此时单方的连贯就建设起来了。
(6)HTTPS握手: 如果应用的是 HTTPS 协定,在通信前还存在 TLS 的一个四次握手的过程。首先由客户端向服务器端发送应用的协定的版本号、一个随机数和能够应用的加密办法。服务器端收到后,确认加密的办法,也向客户端发送一个随机数和本人的数字证书。客户端收到后,首先查看数字证书是否无效,如果无效,则再生成一个随机数,并应用证书中的公钥对随机数加密,而后发送给服务器端,并且还会提供一个后面所有内容的 hash 值供服务器端测验。服务器端接管后,应用本人的私钥对数据解密,同时向客户端发送一个后面所有内容的 hash 值供客户端测验。这个时候单方都有了三个随机数,依照之前所约定的加密办法,应用这三个随机数生成一把秘钥,当前单方通信前,就应用这个秘钥对数据进行加密后再传输。
(7)返回数据: 当页面申请发送到服务器端后,服务器端会返回一个 html 文件作为响应,浏览器接管到响应后,开始对 html 文件进行解析,开始页面的渲染过程。
(8)页面渲染: 浏览器首先会依据 html 文件构建 DOM 树,依据解析到的 css 文件构建 CSSOM 树,如果遇到 script 标签,则判端是否含有 defer 或者 async 属性,要不然 script 的加载和执行会造成页面的渲染的阻塞。当 DOM 树和 CSSOM 树建设好后,依据它们来构建渲染树。渲染树构建好后,会依据渲染树来进行布局。布局实现后,最初应用浏览器的 UI 接口对页面进行绘制。这个时候整个页面就显示进去了。
(9)TCP四次挥手: 最初一步是 TCP 断开连接的四次挥手过程。若客户端认为数据发送实现,则它须要向服务端发送连贯开释申请。服务端收到连贯开释申请后,会通知应用层要开释 TCP 链接。而后会发送 ACK 包,并进入 CLOSE_WAIT 状态,此时表明客户端到服务端的连贯曾经开释,不再接管客户端发的数据了。然而因为 TCP 连贯是双向的,所以服务端仍旧能够发送数据给客户端。服务端如果此时还有没发完的数据会持续发送,结束后会向客户端发送连贯开释申请,而后服务端便进入 LAST-ACK 状态。客户端收到开释申请后,向服务端发送确认应答,此时客户端进入 TIME-WAIT 状态。该状态会继续 2MSL(最大段生存期,指报文段在网络中生存的工夫,超时会被摈弃) 工夫,若该时间段内没有服务端的重发申请的话,就进入 CLOSED 状态。当服务端收到确认应答后,也便进入 CLOSED 状态。
对 rest 参数的了解
扩大运算符被用在函数形参上时,它还能够把一个拆散的参数序列整合成一个数组:
function mutiple(...args) { let result = 1; for (var val of args) { result *= val; } return result;}mutiple(1, 2, 3, 4) // 24
这里,传入 mutiple 的是四个拆散的参数,然而如果在 mutiple 函数里尝试输入 args 的值,会发现它是一个数组:
function mutiple(...args) { console.log(args)}mutiple(1, 2, 3, 4) // [1, 2, 3, 4]
这就是 … rest运算符的又一层威力了,它能够把函数的多个入参收敛进一个数组里。这一点常常用于获取函数的多余参数,或者像下面这样解决函数参数个数不确定的状况。
HTTP和HTTPS协定的区别
HTTP和HTTPS协定的次要区别如下:
- HTTPS协定须要CA证书,费用较高;而HTTP协定不须要;
- HTTP协定是超文本传输协定,信息是明文传输的,HTTPS则是具备安全性的SSL加密传输协定;
- 应用不同的连贯形式,端口也不同,HTTP协定端口是80,HTTPS协定端口是443;
- HTTP协定连贯很简略,是无状态的;HTTPS协定是有SSL和HTTP协定构建的可进行加密传输、身份认证的网络协议,比HTTP更加平安。
ES6中模板语法与字符串解决
ES6 提出了“模板语法”的概念。在 ES6 以前,拼接字符串是很麻烦的事件:
var name = 'css' var career = 'coder' var hobby = ['coding', 'writing']var finalString = 'my name is ' + name + ', I work as a ' + career + ', I love ' + hobby[0] + ' and ' + hobby[1]
仅仅几个变量,写了这么多加号,还要时刻小心外面的空格和标点符号有没有跟错中央。然而有了模板字符串,拼接难度直线降落:
var name = 'css' var career = 'coder' var hobby = ['coding', 'writing']var finalString = `my name is ${name}, I work as a ${career} I love ${hobby[0]} and ${hobby[1]}`
字符串不仅更容易拼了,也更易读了,代码整体的品质都变高了。这就是模板字符串的第一个劣势——容许用${}的形式嵌入变量。但这还不是问题的要害,模板字符串的要害劣势有两个:
- 在模板字符串中,空格、缩进、换行都会被保留
- 模板字符串齐全反对“运算”式的表达式,能够在${}里实现一些计算
基于第一点,能够在模板字符串里无障碍地间接写 html 代码:
let list = ` <ul> <li>列表项1</li> <li>列表项2</li> </ul>`;console.log(message); // 正确输入,不存在报错
基于第二点,能够把一些简略的计算和调用丢进 ${} 来做:
function add(a, b) { const finalString = `${a} + ${b} = ${a+b}` console.log(finalString)}add(1, 2) // 输入 '1 + 2 = 3'
除了模板语法外, ES6中还新增了一系列的字符串办法用于晋升开发效率:
(1)存在性断定:在过来,当判断一个字符/字符串是否在某字符串中时,只能用 indexOf > -1 来做。当初 ES6 提供了三个办法:includes、startsWith、endsWith,它们都会返回一个布尔值来通知你是否存在。
- includes:判断字符串与子串的蕴含关系:
const son = 'haha' const father = 'xixi haha hehe'father.includes(son) // true
- startsWith:判断字符串是否以某个/某串字符结尾:
const father = 'xixi haha hehe'father.startsWith('haha') // falsefather.startsWith('xixi') // true
- endsWith:判断字符串是否以某个/某串字符结尾:
const father = 'xixi haha hehe' father.endsWith('hehe') // true
(2)主动反复:能够应用 repeat 办法来使同一个字符串输入屡次(被间断复制屡次):
const sourceCode = 'repeat for 3 times;'const repeated = sourceCode.repeat(3) console.log(repeated) // repeat for 3 times;repeat for 3 times;repeat for 3 times;
常见的HTTP申请头和响应头
HTTP Request Header 常见的申请头:
- Accept:浏览器可能解决的内容类型
- Accept-Charset:浏览器可能显示的字符集
- Accept-Encoding:浏览器可能解决的压缩编码
- Accept-Language:浏览器以后设置的语言
- Connection:浏览器与服务器之间连贯的类型
- Cookie:以后页面设置的任何Cookie
- Host:发出请求的页面所在的域
- Referer:发出请求的页面的URL
- User-Agent:浏览器的用户代理字符串
HTTP Responses Header 常见的响应头:
- Date:示意音讯发送的工夫,工夫的形容格局由rfc822定义
- server:服务器名称
- Connection:浏览器与服务器之间连贯的类型
- Cache-Control:管制HTTP缓存
- content-type:示意前面的文档属于什么MIME类型
常见的 Content-Type 属性值有以下四种:
(1)application/x-www-form-urlencoded:浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 形式提交数据。该种形式提交的数据放在 body 外面,数据依照 key1=val1&key2=val2 的形式进行编码,key 和 val 都进行了 URL转码。
(2)multipart/form-data:该种形式也是一个常见的 POST 提交形式,通常表单上传文件时应用该种形式。
(3)application/json:服务器音讯主体是序列化后的 JSON 字符串。
(4)text/xml:该种形式次要用来提交 XML 格局的数据。
new操作符的实现原理
new操作符的执行过程:
(1)首先创立了一个新的空对象
(2)设置原型,将对象的原型设置为函数的 prototype 对象。
(3)让函数的 this 指向这个对象,执行构造函数的代码(为这个新对象增加属性)
(4)判断函数的返回值类型,如果是值类型,返回创立的对象。如果是援用类型,就返回这个援用类型的对象。
具体实现:
function objectFactory() { let newObject = null; let constructor = Array.prototype.shift.call(arguments); let result = null; // 判断参数是否是一个函数 if (typeof constructor !== "function") { console.error("type error"); return; } // 新建一个空对象,对象的原型为构造函数的 prototype 对象 newObject = Object.create(constructor.prototype); // 将 this 指向新建对象,并执行函数 result = constructor.apply(newObject, arguments); // 判断返回对象 let flag = result && (typeof result === "object" || typeof result === "function"); // 判断返回后果 return flag ? result : newObject;}// 应用办法objectFactory(构造函数, 初始化参数);
margin 和 padding 的应用场景
- 须要在border外侧增加空白,且空白处不须要背景(色)时,应用 margin;
- 须要在border内测增加空白,且空白处须要背景(色)时,应用 padding。
原型链指向
p.__proto__ // Person.prototypePerson.prototype.__proto__ // Object.prototypep.__proto__.__proto__ //Object.prototypep.__proto__.constructor.prototype.__proto__ // Object.prototypePerson.prototype.constructor.prototype.__proto__ // Object.prototypep1.__proto__.constructor // PersonPerson.prototype.constructor // Person
什么是margin重叠问题?如何解决?
问题形容: 两个块级元素的上外边距和下外边距可能会合并(折叠)为一个外边距,其大小会取其中外边距值大的那个,这种行为就是外边距折叠。须要留神的是,浮动的元素和相对定位这种脱离文档流的元素的外边距不会折叠。重叠只会呈现在垂直方向。
计算准则: 折叠合并后外边距的计算准则如下:
- 如果两者都是负数,那么就去最大者
- 如果是一正一负,就会正值减去负值的绝对值
- 两个都是负值时,用0减去两个中绝对值大的那个
解决办法: 对于折叠的状况,次要有两种:兄弟之间重叠和父子之间重叠 (1)兄弟之间重叠
- 底部元素变为行内盒子:
display: inline-block
- 底部元素设置浮动:
float
- 底部元素的position的值为
absolute/fixed
(2)父子之间重叠
- 父元素退出:
overflow: hidden
- 父元素增加通明边框:
border:1px solid transparent
- 子元素变为行内盒子:
display: inline-block
- 子元素退出浮动属性或定位
Proxy 能够实现什么性能?
在 Vue3.0 中通过 Proxy
来替换本来的 Object.defineProperty
来实现数据响应式。
Proxy 是 ES6 中新增的性能,它能够用来自定义对象中的操作。
let p = new Proxy(target, handler)
target
代表须要增加代理的对象,handler
用来自定义对象中的操作,比方能够用来自定义 set
或者 get
函数。
上面来通过 Proxy
来实现一个数据响应式:
let onWatch = (obj, setBind, getLogger) => { let handler = { get(target, property, receiver) { getLogger(target, property) return Reflect.get(target, property, receiver) }, set(target, property, value, receiver) { setBind(value, property) return Reflect.set(target, property, value) } } return new Proxy(obj, handler)}let obj = { a: 1 }let p = onWatch( obj, (v, property) => { console.log(`监听到属性${property}扭转为${v}`) }, (target, property) => { console.log(`'${property}' = ${target[property]}`) })p.a = 2 // 监听到属性a扭转p.a // 'a' = 2
在上述代码中,通过自定义 set
和 get
函数的形式,在本来的逻辑中插入了咱们的函数逻辑,实现了在对对象任何属性进行读写时发出通知。
当然这是简略版的响应式实现,如果须要实现一个 Vue 中的响应式,须要在 get
中收集依赖,在 set
派发更新,之所以 Vue3.0 要应用 Proxy
替换本来的 API 起因在于 Proxy
无需一层层递归为每个属性增加代理,一次即可实现以上操作,性能上更好,并且本来的实现有一些数据更新不能监听到,然而 Proxy
能够完满监听到任何形式的数据扭转,惟一缺点就是浏览器的兼容性不好。
CSS选择器及其优先级
选择器 | 格局 | 优先级权重 |
---|---|---|
id选择器 | #id | 100 |
类选择器 | #classname | 10 |
属性选择器 | a[ref=“eee”] | 10 |
伪类选择器 | li:last-child | 10 |
标签选择器 | div | 1 |
伪元素选择器 | li:after | 1 |
相邻兄弟选择器 | h1+p | 0 |
子选择器 | ul>li | 0 |
后辈选择器 | li a | 0 |
通配符选择器 | * | 0 |
对于选择器的优先级:
- 标签选择器、伪元素选择器:1
- 类选择器、伪类选择器、属性选择器:10
- id 选择器:100
- 内联款式:1000
注意事项:
- !important申明的款式的优先级最高;
- 如果优先级雷同,则最初呈现的款式失效;
- 继承失去的款式的优先级最低;
- 通用选择器(*)、子选择器(>)和相邻同胞选择器(+)并不在这四个等级中,所以它们的权值都为 0 ;
- 样式表的起源不同时,优先级程序为:内联款式 > 外部款式 > 内部款式 > 浏览器用户自定义款式 > 浏览器默认款式。
如何判断一个对象是否属于某个类?
- 第一种形式,应用 instanceof 运算符来判断构造函数的 prototype 属性是否呈现在对象的原型链中的任何地位。
- 第二种形式,通过对象的 constructor 属性来判断,对象的 constructor 属性指向该对象的构造函数,然而这种形式不是很平安,因为 constructor 属性能够被改写。
- 第三种形式,如果须要判断的是某个内置的援用类型的话,能够应用 Object.prototype.toString() 办法来打印对象的[[Class]] 属性来进行判断。
为什么须要革除浮动?革除浮动的形式
浮动的定义: 非IE浏览器下,容器不设高度且子元素浮动时,容器高度不能被内容撑开。 此时,内容会溢出到容器里面而影响布局。这种景象被称为浮动(溢出)。
浮动的工作原理:
- 浮动元素脱离文档流,不占据空间(引起“高度塌陷”景象)
- 浮动元素碰到蕴含它的边框或者其余浮动元素的边框停留
浮动元素能够左右挪动,直到遇到另一个浮动元素或者遇到它外边缘的蕴含框。浮动框不属于文档流中的一般流,当元素浮动之后,不会影响块级元素的布局,只会影响内联元素布局。此时文档流中的一般流就会体现得该浮动框不存在一样的布局模式。当蕴含框的高度小于浮动框的时候,此时就会呈现“高度塌陷”。
浮动元素引起的问题?
- 父元素的高度无奈被撑开,影响与父元素同级的元素
- 与浮动元素同级的非浮动元素会追随其后
- 若浮动的元素不是第一个元素,则该元素之前的元素也要浮动,否则会影响页面的显示构造
革除浮动的形式如下:
- 给父级div定义
height
属性 - 最初一个浮动元素之后增加一个空的div标签,并增加
clear:both
款式 - 蕴含浮动元素的父级标签增加
overflow:hidden
或者overflow:auto
- 应用 :after 伪元素。因为IE6-7不反对 :after,应用 zoom:1 触发 hasLayout**
.clearfix:after{ content: "\200B"; display: table; height: 0; clear: both; } .clearfix{ *zoom: 1; }
如何应用for...of遍历对象
for…of是作为ES6新增的遍历形式,容许遍历一个含有iterator接口的数据结构(数组、对象等)并且返回各项的值,一般的对象用for..of遍历是会报错的。
如果须要遍历的对象是类数组对象,用Array.from转成数组即可。
var obj = { 0:'one', 1:'two', length: 2};obj = Array.from(obj);for(var k of obj){ console.log(k)}
如果不是类数组对象,就给对象增加一个[Symbol.iterator]属性,并指向一个迭代器即可。
//办法一:var obj = { a:1, b:2, c:3};obj[Symbol.iterator] = function(){ var keys = Object.keys(this); var count = 0; return { next(){ if(count<keys.length){ return {value: obj[keys[count++]],done:false}; }else{ return {value:undefined,done:true}; } } }};for(var k of obj){ console.log(k);}// 办法二var obj = { a:1, b:2, c:3};obj[Symbol.iterator] = function*(){ var keys = Object.keys(obj); for(var k of keys){ yield [k,obj[k]] }};for(var [k,v] of obj){ console.log(k,v);}
数组有哪些原生办法?
- 数组和字符串的转换方法:toString()、toLocalString()、join() 其中 join() 办法能够指定转换为字符串时的分隔符。
- 数组尾部操作的办法 pop() 和 push(),push 办法能够传入多个参数。
- 数组首部操作的办法 shift() 和 unshift() 重排序的办法 reverse() 和 sort(),sort() 办法能够传入一个函数来进行比拟,传入前后两个值,如果返回值为负数,则替换两个参数的地位。
- 数组连贯的办法 concat() ,返回的是拼接好的数组,不影响原数组。
- 数组截取方法 slice(),用于截取数组中的一部分返回,不影响原数组。
- 数组插入方法 splice(),影响原数组查找特定项的索引的办法,indexOf() 和 lastIndexOf() 迭代办法 every()、some()、filter()、map() 和 forEach() 办法
- 数组归并办法 reduce() 和 reduceRight() 办法
单行、多行文本溢出暗藏
- 单行文本溢出
overflow: hidden; // 溢出暗藏text-overflow: ellipsis; // 溢出用省略号显示white-space: nowrap; // 规定段落中的文本不进行换行
- 多行文本溢出
overflow: hidden; // 溢出暗藏text-overflow: ellipsis; // 溢出用省略号显示display:-webkit-box; // 作为弹性伸缩盒子模型显示。-webkit-box-orient:vertical; // 设置伸缩盒子的子元素排列形式:从上到下垂直排列-webkit-line-clamp:3; // 显示的行数
留神:因为下面的三个属性都是 CSS3 的属性,没有浏览器能够兼容,所以要在后面加一个-webkit-
来兼容一部分浏览器。