js数据类型
基本数据类型:Number,String ,Boolean,undefined,null, Symbol ( ES6 ) ,
引用数据类型:Object ,Array ,Map( ES6 ) ,Set( ES6 ) ,
数据类型检测
typeof
可检测基本数据类型和function,无法检测引用数据类型
var arr = [
null, / / object
undefined, / / undefined
true , / / boolean
12 , / / number
'haha' , / / string
Symbol ( ) , / / symbol
20 n, / / bigint
function( ) { } , / / function
{ } , / / object
[ ] , / / object
]
for ( let i = 0 ; i < arr. length; i+ + ) {
console. log( typeof arr[ i] )
}
js语言特性
一、运行在客户端浏览器上的脚本语言、解释性语言
二、不用预编译,直接解析执行代码
三、是弱类型语言, 较为灵活, 基于原型的语言, 内置支持类型
四、与操作系统无关,跨平台的语言
五、解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML 网页上使用,用来给HTML 网页增加动态功能。JavaScript兼容于ECMA 标准,因此也称为ECMAScript。
Javascript的特点:
一、简单性:
JavaScript是一种基于Java基本语句和控制流之上的简单而紧凑的设计,从而对于学习Java是一种非常好的过渡。它的变量类型是采用弱类型,并未使用严格的数据类型。
二、动态性:
JavaScript是动态的,它可以直接对用户或客户输入做出响应,无须经过Web服务程序。它对用户的反映响应,是采用以事件驱动的方式进行的。所谓事件驱动,就是指在主页( Home Page) 中执行了某种操作所产生的动作,就称为“事件”( Event) 。比如按下鼠标、移动窗口、选择菜单等都可以视为事件。当事件发生后,可能会引起相应的事件响应。
三、跨平台性:
JavaScript是依赖于浏览器本身,与操作环境无关,只要能运行浏览器的计算机,并支持JavaScript的浏览器就可正确执行。从而实现了“编写一次, 走遍天下”的梦想。
四、安全性:
JavaScript是一种安全性语言,它不允许访问本地的硬盘,并不能将数据存入到服务器上,不允许对网络文档进行修改和删除,只能通过浏览器实现信息浏览或动态交互。从而有效地防止数据的丢失。
动态语言的特性:
var num= 10 ; / / num是一个数字类型
num= "jim" ; / / 此时num又变成一个字符串类型
/ / 我们把一个变量用来保存不同数据类型的语言称之为一个动态语言,或者说是一个弱类型语言
静态语言:c
/ / 静态语言在声明一个变量就已经确定了这个变量的数据类型,
int c; / / c就是整数类型
/ / 我们把这种声明一个变量就确定了它的数据类型这样的语言称之为静态语言,也称之为强类型语言
/ / 而且在任何时候都不可以改变他的数据类型
闭包产生的原因
受JavaScript链式作用域结构的影响,父级变量中无法访问到子级的变量值,为了解决这个问题,才使用闭包这个概念;
CSS盒模型
1. 盒模型:就是把HTML 页面中的元素看作是以一个矩形的盒子,也就是一个装东西的容器。
2. 盒模型包含四部分:内容(content)、内边距也称之为补白和填充区(padding)
边框(border)外边距(margin)
标准模型:width = 内容content 的宽度;( 默认)
设置方式: box- sizing:content - box;
IE 模型:width = 内容content + 边框border + 内边距paddig 的宽度;
设置方式: box- sizing:border - box;
行内元素和块级元素区别
1. 行内元素与块级元素直观上的区别
行内元素会在一条直线上排列,都是同一行的,水平方向排列
块级元素各占据一行,垂直方向排列。块级元素从新行开始结束接着一个断行。
2. 块级元素可以包含行内元素和块级元素。行内元素不能包含块级元素。
3. 行内元素与块级元素属性的不同,主要是盒模型属性上
行内元素设置width无效,height无效( 可以设置line- height) ,margin上下无效,padding上下无效
重排和重绘
1. 重绘(repaint或redraw):当盒子的位置、大小以及其他属性,例如颜色、
字体大小等都确定下来之后,浏览器便把这些原色都按照各自的特性绘制一遍,
将内容呈现在页面上。重绘是指一个元素外观的改变所触发的浏览器行为,
浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。
触发重绘的条件:改变元素外观属性。如:color,background- color等。
2. 重排(重构/ 回流/ reflow):当渲染树中的一部分( 或全部) 因为元素的规模尺寸,布局,
隐藏等改变而需要重新构建, 这就称为回流( reflow) 。每个页面至少需要一次回流,
就是在页面第一次加载的时候。
3. 重绘和重排的关系:在回流的时候,浏览器会使渲染树中受到影响的部分失效,
并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程称为重绘。
重排必定会引发重绘,但重绘不一定会引发重排。
( 1 ) 触发重排的条件:任何页面布局和几何属性的改变都会触发重排,比如:
1 、页面渲染初始化;( 无法避免)
2 、添加或删除可见的DOM 元素;
3 、元素位置的改变,或者使用动画;
4 、元素尺寸的改变——大小,外边距,边框;
5 、浏览器窗口尺寸的变化(resize事件发生时);
6 、填充内容的改变,比如文本的改变或图片大小改变而引起的计算值宽度和高度的改变;
7 、读取某些元素属性:(offsetLeft/ Top/ Height/ Width,
clientTop/ Left/ Width/ Height, scrollTop/ Left/ Width/ Height,
width/ height, getComputedStyle( ) , currentStyle( IE ) )
( 2 ) 重绘发生的情况:
重绘发生在元素的可见的外观被改变,但并没有影响到布局的时候。比如,
仅修改DOM 元素的字体颜色(只有Repaint,因为不需要调整布局)
事件的捕获和冒泡,冒泡的使用场景
1. 事件冒泡是指,事件会从最内层的元素开始发生,一直向上传播,直到document对象。
事件冒泡可以形象地比喻为把一颗石头投入水中,泡泡会一直从水底冒出水面。
2. 而事件捕获与事件冒泡相反,事件会从最外层开始发生,直到最具体的元素。
3. 使用场景:例如一条购物车信息,在这条信息中,右下角有一个删除按钮。点击这条消息可查看详情,
点击删除按钮可将此商品移除。我们会分别给信息的div和删除button添加一个冒泡的click事件监听。
如果不做阻止传递,点击删除button后,会显示商品详情。显然这不是我们想看到的。
这时我们给button一个阻止事件传递的功能,点击删除按钮后,事件就会结束,就不再显示商品详情。
cookie,localstorage,sessionstorage
共同点:都是保存在浏览器端、且同源的
不同点:
1. cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。
cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下
sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。
2. 存储大小限制也不同,cookie数据不能超过4 K,sessionStorage和localStorage可以达到5 M
3. sessionStorage:仅在当前浏览器窗口关闭之前有效;
localStorage:始终有效,窗口或浏览器关闭也一直保存,本地存储,因此用作持久数据;
cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭
4. 作用域不同
sessionStorage:不在不同的浏览器窗口中共享,即使是同一个页面;
localstorage:在所有同源窗口中都是共享的;也就是说只要浏览器不关闭,数据仍然存在
cookie : 也是在所有同源窗口中都是共享的. 也就是说只要浏览器不关闭,数据仍然存在
跨域,解决跨域的方法,jsonp具体原理
因为浏览器出于安全考虑,有同源策略。也就是说,如果协议、域名或者端口有一个不同就是跨域,Ajax 请求会失败。
为来防止CSRF 攻击
1. JSONP
JSONP 的原理很简单,就是利用 < script> 标签没有跨域限制的漏洞。
通过 < script> 标签指向一个需要访问的地址并提供一个回调函数来接收数据当需要通讯时。
< script src= "http://domain/api?param1=a¶m2=b&callback=jsonp" > < / script>
< script>
function jsonp( data) {
console. log( data)
}
< / script>
JSONP 使用简单且兼容性不错,但是只限于 get 请求。
2. CORS
CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。
3. document. domain
该方式只能用于二级域名相同的情况下,比如 a. test. com 和 b. test. com 适用于该方式。
只需要给页面添加 document. domain = 'test.com' 表示二级域名都相同就可以实现跨域
4. webpack配置proxyTable设置开发环境跨域
首先需要明白webpack proxy跨域只能用作与开发阶段,临时解决本 地请 求服务器产生的跨域问题。
并不适合线上环境。配置在webpack的devServer属性中。
webpack中的devsever配置后,打包阶段在本地临时生成了一个node服务器,浏览器请求服务器相当于请求本地服务。
5. nginx代理跨域
6. iframe跨域
7. postMessage
这种方式通常用于获取嵌入页面中的第三方页面数据。一个页面发送消息,另一个页面判断来源并接收消息
前端安全问题,攻击
1. XSS 跨站脚本攻击是指恶意攻击者利用网站没有对用户提交数据进行转义处理或者过滤不足的缺点,
进而添加一些代码,嵌入到web页面中去。使别的用户访问都会执行相应的嵌入代码。从而盗取用户资料、
利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。
主要原理:过于信任客户端提交的数据!
防御手段:不信任任何客户端提交的数据,只要是客户端提交的数据就应该先进行相应的过滤处理,然后方可进行下一步的操作。
2. CSRF 跨站请求伪造是指黑客引诱用户打开黑客的网站,在黑客的网站中,利用用户的登录状态发起跨站请求。
当用户在某网页登录之后,在没有关闭网页的情况下,收到别人的链接。点击链接,会利用浏览器的cookie把密码改掉。
主要原理:在没有关闭相关网页的情况下,点击其他人发来的CSRF 链接,利用客户端的cookie直接向服务器发送请求。
防御手段:检测Referer, Anti- CSRF , token机制, 业务上要求用户输入原始密码(简单粗暴),
攻击者在不知道原始密码的情况下,无论如何都无法进行CSRF 攻击。
3. Sql脚本注入
利用现有应用程序,将(恶意)的SQL 命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)
SQL 语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL 语句
主要原理:通过把SQL 命令插入到Web表单提交或输入域名或页面请求的查询字符串,
最终达到欺骗服务器执行恶意的SQL 命令。
防御手段:使用预编译,绑定变量(推荐)。检查数据类型。过滤特殊字符和语句。页面不错误回显。
前端性能优化
1 、降低请求量
① 合并资源,减少http请求数量。
② lazyLoad,如图片懒加载。分批加载,每次只加载一部分。
③ 使用字体图标或CSS 绘制,来代替部分图片。
2 、加快请求速度
① 预解析DNS
② 使用HTTP2 .0
③ 并行加载
④ CDN 分发
⑤ webP,对图片进行压缩,减少图片体积。
⑥ minify/ gzip 压缩,对css、js等文件进行压缩(去除空格、回车等),减少文件体积
补充知识:
webP 的优势体现在它具有更优的图像数据压缩算法,能带来更小的图片体积,而且图像质量几乎无差异。同时具备了无损和有损的压缩模式、Alpha 透明以及动画的特性,在 JPEG 和 PNG 上的转化效果都相当优秀。
Minify把 CSS 和 JS 压缩和削减( Minify:去掉空格回车符等) ,以及把多个CSS ,JS 文件整合到一个文件里。
3 、缓存
① HTTP 协议缓存请求
② 离线缓存 manifest
③ 本地缓存 localStorage
补充知识:
GET 请求可以缓存,POST 请求不能缓存。GET 请求后退/ 刷新无害,POST 后退/ 刷新则会致使重新提交数据
4 、渲染
① JS 优化,如防抖、节流、事件委托、减少重排重绘等。
② CSS 优化,如提取公共样式减少代码量、减少选择器嵌套层数、精灵图等。
③ 服务器端渲染
④ 使用Web Workers
⑤ CSS 写在文件头部,JS 写在文件底部。
v-if和v-show的区别
v- show
v- show指令的作用是:根据真假值切换元素的显示状态, 是响应式的
语法表达v- show = " 表达式 "
原理是修改元素的的CSS 属性( display) 来决定实现显示还是隐藏
指令后面的内容最终都会解析为布尔值
值为真( true ) 的时候元素显示,值为假( false ) 的时候元素隐藏
数据改变之后呢对应的元素的显示状态也是会同步更新的
v- if 指令的作用:根据表达式的真假切换元素的显示状态
v- if = "表达式"
本质是通过操纵dom元素来进行切换显示
表达式的值为true 的时候元素存在于dom树中,为false 的时候从dom树中移除
原理:
v- show指令:元素始终被渲染到HTML ,它只是简单的伪元素设置css的style属性,当不满足条件的元素被设置style= “display:none”的样,是通过修改元素的的CSS 属性( display) 来决定实现显示还是隐藏
v- if 指令:满足条件是会渲染到html中,不满足条件时是不会渲染到html中的,是通过操纵dom元素来进行切换显示
应用场景:
v- if 需要操作dom元素,有更高的切换消耗,v- show只是修改元素的的CSS 属性有更高的初始渲染消耗,如果需要非常频繁的切换,建议使用v- show较好,如果在运行时条件很少改变,则使用v- if 较好
vue生命周期
当Vue对象创建之前触发的函数(beforeCreate)
Vue对象创建完成触发的函数( Created)
当Vue对象开始挂载数据的时候触发的函数( beforeMount)
当Vue对象挂载数据的完成的时候触发的函数( Mounted)
Vue对象中的data数据发生改变之前触发的函数 ( beforeUpdate)
Vue对象中的data数据发生改变完成触发的函数( Updated)
Vue对象销毁之前触发的函数 ( beforeDestroy)
Vue对象销毁完成触发的函数( Destroy)
数据请求在哪个生命周期
看实际情况,一般在 created(或beforeCreated) 里面就可以,如果涉及到需要页面加载完成之后的话就用 mounted。
在created的时候,视图中的html并没有渲染出来,所以此时如果直接去操作html的dom节点,一定找不到相关的元素
而在mounted中,由于此时html已经渲染出来了,所以可以直接操作dom节点,(此时document. getelementById 即可生效了)
created和mounted有什么区别,使用场景?
created:在模板渲染成 html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted :在模板渲染成 html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
其实两者比较好理解,通常created使用的次数多,而mounted通常是在一些插件的使用或者组件的使用中进行操作
在created的时候,视图中的html并没有渲染出来,所以此时如果直接去操作html的dom节点,一定找不到相关的元素
而在mounted中,由于此时html已经渲染出来了,所以可以直接操作dom节点,
MVVM
MVVM ,是Model- View- ViewModel的简写,是M - V - VM 三部分组成。它本质上就是MVC 的改进版。
MVVM 就是将其中的View 的状态和行为抽象化,其中ViewModel将视图 UI 和业务逻辑分开,
它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑。
MVVM 采用双向数据绑定,view中数据变化将自动反映到viewmodel上,反之,
model中数据变化也将会自动展示在页面上。把Model和View关联起来的就是ViewModel。
ViewModel负责把Model的数据同步到View显示出来,还负责把View的修改同步回Model。
MVVM 核心思想,是关注model的变化,让MVVM 框架利用自己的机制自动更新DOM ,也就是所谓的数据- 视图分离,
数据不会影响视图。
虚拟DOM
1. 什么是虚拟dom?
虚拟dom本质上就是一个普通的JS 对象,用于描述视图的界面结构
在vue中,每个组件都有一个render函数,每个render函数都会返回一个虚拟dom树,
这也就意味着每个组件都对应一棵虚拟DOM 树
2. 为什么需要虚拟dom?
在vue中,渲染视图会调用render函数,这种渲染不仅发生在组件创建时,同时发生在视图依赖的数据更新时。
如果在渲染时,直接使用真实DOM ,由于真实DOM 的创建、更新、插入等操作会带来大量的性能损耗,
从而就会极大的降低渲染效率。
因此,vue在渲染时,使用虚拟dom来替代真实dom,主要为解决渲染效率的问题。
3. 虚拟dom是如何转换为真实dom的?
在一个组件实例首次被渲染时,它先生成虚拟dom树,然后根据虚拟dom树创建真实dom,
并把真实dom挂载到页面中合适的位置,此时,每个虚拟dom便会对应一个真实的dom。
如果一个组件受响应式数据变化的影响,需要重新渲染时,它仍然会重新调用render函数,
创建出一个新的虚拟dom树,用新树和旧树对比,通过对比,vue会找到最小更新量,然后更新必要的真实dom节点
这样一来,就保证了对真实dom达到最小的改动。
手撕,字符串中出现次数最多的字符次数
var str = 'asdasddsfdsfadsfdghdadsdfdgdasd'
str = str. split( '' ) ;
console. log( str) ;
var newStr = { } ;
/ / 数组去重 和计算出现的次数
str. forEach( function ( item) {
if ( newStr[ item] ) {
newStr[ item] + + ;
} else {
newStr[ item] = 1 ;
}
} )
var max= 0 ;
var strkey= null;
for ( var key in newStr) {
if ( newStr[ key] > max) {
max= newStr[ key] ;
strkey= key;
}
}
console. log( "最多的字符是" + strkey) ;
console. log( "出现的次数是" + max) ;
手撕,url的参数,以对象的形式写出来
var search= "?uname=dingdin&upwd=12345&favs=swimming&favs=running&favs=music" ;
function searchObj( str) {
/ / 去掉?
var str= str. slice( 1 ) ;
/ / 根据“& ”分割字符串
var arr= str. split( "&" ) ;
/ / 定义空的obj,保存对象
var obj= { } ;
/ / 循环遍历分割后的数组
for ( var p of arr) {
/ / 根据“= ”分割
var arr2= p. split( "=" ) ;
/ / 解构
var [ name, value] = arr2;
/ / 如果obj中的name为undefined就把值填进去,否则就连接
if ( obj[ name] == undefined) {
obj[ name] = value;
} else {
obj[ name] = [ ] . concat( value, obj[ name] )
}
}
return obj;
}
var a= searchObj( search) ;