基础知识
变量类型和计算
题目
- js中使用typeof能得到哪些类型
- string
- boolean
- number
- undefined
- object
- function
- 何时使用===何时使用==
- 尽量全部使用===
a === undefined || a=`` ``null 时可以 a`` ``null
- JS中有哪些内置函数 - 数据封装类对象
- Object
- Array
- Boolean
- Number
- String
- Function
- Date
- RegExp
- Error
- JS变量按照存储方式区分为哪些类型,并描述其特点
- 值类型:值类型复制是真正的拷贝,不会互相干预
- 引用类型:是引用的赋值,会互相干预
- 如何理解JSON
- JSON是一个JS对象,内置在JS语法里。
- JSON同时也是一种数据格式。
值类型
为了公用内存空间,减少空间占用。
typeof 5种值
- 值类型
- typeof undefiend
- typeof “abc”
- typeof 123
- typeof true
- 引用类型
- typeof {} typeof [] typeof null
- typeof console.log // function
typeof只能区分值类型,函数是特殊的应用类型,在Js中非常重要,使得更加容易用typeof检测出来
变量计算-强制类型转换
字符串拼接
== 运算符
100 == "100"null == undefined //都转为了false0 == '' //都转为了false
if语句
逻辑运算符
10 && 0 //0""||"abc" //"abc"!window.abc //true//判断一个变量会被当作true还是falsevar a = 100;!!a
原型和原型链
题目
- 如何准确判断一个变量是数组类型
- 使用Array.isArray
- arr instanceof Array
- 写一个原型链的例子
- new一个对象的过程
- 创建一个新对象
- this指向这个新对象
- 执行代码,对this复赋值
- 返回this
- zepto源码中如何使用原型链
封装一个DOM查询的例子
function Elem(id){this.elem=document.getElementById(id)}Elem.prototype.html=function(val){var elem=this.elemif(val){elem.innerHtml=value;return this;}else{return ele.innerHTML;}}Elem.prototype.on=function(type,fn){var elem=this.elemelem.addEventListener(type,fn)}var div1=new Elem('div1')console.log(div1.html())
构造函数
-
构造函数扩展
var a = {} 是var a = new Object() 语法糖
- var a = [] 是 var a = new Array()
- function Fun 是 var Foo = new Function
- 使用instanceof 判断一个函数是否是一个变量的构造函数
原型规则和示例
- 所有的应用类型都具有对象的特性(数组、对象、函数除了null),即可自由有扩展属性。
- 所有的引用类型都有一个proto【隐式原型】属性,属性值是一个普通对象。
- 所有的函数,都有一个prototype属性【显示原型】,属性值也是一个普通的对象。
- 所有的引用类型(数组,对象,函数),proto属性值指向(完全等)它的构造函数的prototype属性值。
- 当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的proto(即构造函数的prototype)中寻找。
this
使用for in 循环对象的自身属性,高级浏览器屏蔽了来自原型的属性,建议在通过hasOwnProperty再判断下
原型链
instanceof
用于判断引用类型属于哪个函数的构造方法
instanceof判断的逻辑:
- f的proto一层一层往上,能否对应到Foo.prorotype
- 再试着判断f instanceof Object
作用域和闭包
题目
对于变量提升的理解
- 变量定义
- 函数声明(注意和函数表达式的区别)
函数声明比变量声明更置顶 (函数在变量上面) 变量赋值>函数声明>变量声明
this几种不同的使用场景
- 构造
- 普通
- 对象属性
- call,apply,bind
- 创建10个a标签,点击弹出来对应的序号
```javascript
var i ,a
for (i=0;i<10;i++){
a=document.createElement(‘a’)
a.innerHTML= i + “
“ a.addEventListener(‘click’,function (e){ e.preventDefault() alert(i) }) document.body.appendChild(a) } // 注意:addEventListener 是点击才执行的,点击a标签时执行,i是自由变量,去父作用域找是10
var i ,a
for (i=0;i<10;i++){
(function(i){
a=document.createElement(‘a’)
a.innerHTML= i + “
“
a.addEventListener(‘click’,function (e){
e.preventDefault()
alert(i)
})
document.body.appendChild(a)
})(i)
}
var a
for (let i=0;i<10;i++){
a=document.createElement(‘a’)
a.innerHTML= i + “
“
a.addEventListener(‘click’,function (e){
e.preventDefault()
alert(i)
})
document.body.appendChild(a)
}
4. 如何理解作用域1. 自由变量1. 作用域链,即自由变量的查找1. 闭包的两个场景。5. 实际开发中闭包的应用1. 封装变量,收敛权限。<a name="ldMaT"></a>### 执行上下文- 范围:一段<script>或者一个函数。- 全局:变量定义、函数声明,执行强先把这两个拿出来。- 函数:变量定义、函数声明、this、argumnets。在执行前把这些拿出来。- 注意函数声明和函数表达式。```javascriptconsole.log(a) // undefiendvar a=100fn('zhangsan') // 张三 20function fn(name){// 函数声明age=20;console.log(name,age);var age}// 执行第一行前,会把所有的变量声明(通过undefined占位)和函数声明拿出来// 进入到fn函数里时,变量定义、函数声明、this,argumnets拿出来。// 函数表达式var fn2 = function (){}
this
var a={name:"A",fn:function (){console.log(this.name)}}a.fn() //this===aa.fn.call({name:"B"}) // this=== {name:"B"}var fn1=a.fnfn1() // this===window
- this要在执行时确认,定义时无法确认。
四种
// 无快级别作用域if(true){var name = "zhangsan"}console.log(name)// 等同于var nameif(true){name="zhangsan"}console.log(name)// 函数和全局作用域var a= 100function fn(){var a=200console.log('fn',a)}console.log("global",a)fn()
if(true){let name = "zhangsan"}console.log(name)
作用域链
当前作用域没有定义的变量,即为“自由变量”
链指的不断向父级寻找。
var a = 100;function fn(){// 当前作用域没有定义的变量,即为“自由变量”var b = 200;// 当前作用域没有定义变量a,就要去其父级作用域去找,函数的父级作用域是函数定义的作用域。console.log(a);console.log(b)}fn()
var a = 100;function F1(){// F1的父级是全局var b=200;function F2(){// F2的父级是F1,因为在F1中定义var c = 300;console.log(a) // a是自由变量console.log(b) // b是自由变量console.log(c)}F2()}F1()
闭包
function F1(){var a=100// 返回一个函数return function(){// a是自由变量console.log(a)}}var f1=F1()var a = 200; // 这里的是全局作用域的af1()// 100 在找的时候看定义的时候的作用域,所以是100
场景
- 函数作为返回值
- 函数作为参数传递
```javascript
// 函数作为参数传递
function F1(){
var a=100
// 返回一个函数
return function(){
// a是自由变量
} }console.log(a)
var f1=F1() function F2(fn){ var a=200 fn() } F2(f1)
<a name="6uGan"></a>## 异步和单线程<a name="546Et"></a>### 题目<a name="5A9HX"></a>#### 同步和异步的区别是什么?分别举一个同步和异步的例子- 同步会阻塞执行,异步不会- alert是同步,setTimeout异步<a name="oHubm"></a>#### 关于setTimeout<a name="5h91l"></a>#### 前端使用异步的场景有哪些需要等待=>等待不能卡顿,所以有异步。<a name="dz8tr"></a>### 什么是异步(对比同步)```javascript// 异步console.log(100)setTimeout(function(){console.log(200)},1000)console.log(300)// 同步console.log(100)alert(200);console.log(300)
- 有没有阻塞程序运行
何时需要异步
- 在可能发生等待的情况
- 等待过程中不能像alert一样阻塞程序运行
- 因此,所以的“等待的情况”都需要异步
前端使用异步的场景
- 定时任务:setTimeout ,setInterval
- 网络请求:ajax请求,动态
加载
- 事件绑定
异步和单线程
```javascript // 异步 console.log(100) setTimeout(function(){ console.log(200) }) console.log(300)
// 100 // 300 // 200
单线程的特点,不能同时干两件事<a name="c1poD"></a>## 日期和math- 获取2017-06-10格式日期- 获取随机数,要求长度一致的字符串格式- 可以遍历对象和数组的通用的forEach函数<a name="yKPV7"></a>### 日期```javascriptDate.now()var dt=new Date()dt.getTime()dt.getFullYear()dt.getMonth()dt.getDate()dt.getHours()dt.getMinutes()dt.getSeconds()
Math
Math.random
数组
JS-Web-API
- js基础 基于(ECMA262标准,规定基础语法规则)
- 变量类型和计算
- 原型和原型链
- 闭包和作用域
- 异步和单线程
- 其他(如日期、Math、JSON、各种常用的API)
JS-Web-API(W3C标准)
- 获取元素document.getElementById()
- 定义一个document全局变量
- 给他定义一个getElementById属性,属性值是一个函数。
W3C标准
- 没有规定任何JS基础相关的东西
- 不管变量类型,原型,作用域和异步
- 只管定义用于浏览器中JS操作页面的API和全局变量
JS内置的全局函数和对象
- Object
- Array
- Boolean
- String
- Math
- JSON等
- window
- document
- navigator
- …
常说的JS(浏览器执行的JS)
- JS基础知识
-
DOM(Dom Object Mode)
题目
DOM是基于哪种基本的数据结构
DOM常用的API
DOM节点的attr和property有何区别
property只是一个JS对象的属性的修改
- Attribute是对html标签属性的修改和获取
DOM本质
DOM节点操作
获取DOM节点
- getElementById
- getElementByTagName
- getElementByClassName
- querySelectorAll
property
```javascript var pList =document.querySelectorAll(‘p’) var p = pList[0] // p是JS对象,指向的是p标签 p.style.width p.className p.nodeName p.nodeType
// 浏览器扩展了对象的属性,实现了W3C标准。 // nodeType 是 p的属性property
<a name="sV9Uc"></a>#### Attribute```javascriptvar pList =document.querySelectorAll('p')var p = pList[0] // p是JS对象,指向的是p标签p.getAttribute('data-name')p.setAttribute('data-name','imooc')p.getAttribute('style')p.setAttribute('style','font-size:30px;')// p的一个属性getAttribute(),里面的参数是标签的属性。//比如class,href。这个attribute是文的标记,是有关文档的// 是修改DOM里的属性值的。
DOM结构操作
// 新增节点// 添加新节点var p1=document.createElement('p')p1.innerHTML="this si p1"div1.appendChild(p1)// 移动已有节点var p2=document.getElementById('p2')div1.appendChild(p2)div1.parentElement //获取父元素div1.childNodes //获取子元素// 删除节点
BOM(Browser Object Mode)
题目
- 如何检测浏览器/系统的类型,(移动端针对于安卓/IOS特性的适配,针对于APP内嵌页的交互的适配)
- 拆解url的各部分
navigator
var ua=navigator.userAgent;var isChrome=ua.indexOf('Chrome')
screen
screen.widthscreen.height
location
location.hreflocation.protocollocation.pathnamelocation.searchlocation.hash
history
history.back()history.forward()
事件
题目
编写一个通用的事件监听函数
描述事件冒泡的流程
通用事件绑定
btn.addEventListener('click',function(){})// 可以简单封装,因为上面的没法压缩,使用复杂等。// IE低版本使用attachEvent绑定事件,和W3C标准不一样,用量少,不支持,// 官方已经放弃。了解兼容性即可。没有必要学习
事件冒泡
e.stopPropatation()
代理
//Element.matches()函数
Ajax
题目
手动编写一个ajax、不依赖第三方库
跨域的几种实现方式
- JSONP
- HttpHeader
XMLHttpRequest
```javascript var xhr = new XMLHttpRequest() xhr.open(“get”,”/api”,false) xhr.onreadystatechange=function(){ // 这里的函数异步执行,可参考之前 js基础中的异步模块 if(xhr.readyState==4){ if(xhr.status==200){
} } }alert(responsetext)
xhr.send(null)
<a name="N3avp"></a>### readyState状态码说明- 0:(未初始化)未初始化,还没有send- 1:(载入)已调用send,正在发送请求- 2:(载入完成)send方法执行完成,已经接收到全部相应内容- 3:(交互)正在解析相应内容- 4:(完成)相应内容解析完成- xhr.status- 200:请求成功- 300:重定向- 400:客户端错误- 500:服务端错误<a name="FSZh4"></a>## 跨域<a name="enqi3"></a>### 什么是跨域- 浏览器的同源策略,不允许ajax访问其他接口- 条件:协议、域名、端口,有一个不同就是跨域<a name="Vbky8"></a>### 可以跨域的三个标签- img src- img用于打点统计,统计网站可能是其他域- link href- CDN- script- CDN- JSONP<a name="C6HrJ"></a>### 跨域注意事项- 所有的跨域请求都必须经过信息提供方允许- 如果未经允许可获取,是浏览器同源策略出现漏洞<a name="R4XDq"></a>### JSONP<a name="3J0hM"></a>##### 原理:1. **服务器可以根据请求,动态生成一个文件,返回**1. 返回的内容格式callback({x:100,y:200})(动态生成)<a name="f4tG0"></a>### 服务端设置http header- 另外一个解决跨域的简介方法,需要服务端来做- 作为交互方,必须知道- 跨域的趋势```javascriptconst allowCrossDomain = function (req, res, next) {res.header('Access-Control-Allow-Origin', '*');res.header('Access-Control-Allow-Origin', 'http://a.com,http://b.com');res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');res.header('Access-Control-Allow-Headers', 'Content-Type');res.header('Access-Control-Allow-Credentials', 'true');next();};
存储
题目
cookie,sessionStorage和localStorage的区别
用于存储的缺点
- 存储量太少4kb。
- 所有http请求都会携带,会影响获取资源的效率
-
localStorage和sessionStorage
HTML5专门为存储而设计,最大5MB
- API简洁易用
- localStorage.setItem(key,value);localStorage.getItem(key)
- ios safari隐藏模式下,localStorage会报错,建议trycatch
通用
- 通过export暴露出来,使用requrie引用,
-
AMD
require.js
- 全局定义define函数
- 全局定义require函数
依赖JS自动异步加载
// util.jsdefine(function () {return {getformatedata(){}}})
// a-util.jsdefine(['./util.js'],function (util) {return {getformatedata(data){return util.getformatedata(data,2)}}})
// a.jsdefine(['./a-util.js'],function (aUtil) {return {getformatedata(data){return aUtil.getformatedata(data,2)}}})
CommonJs
nodejs模块化规范,现在被前端大量使用,原因:
- 前端开发依赖的插件和库,都可以丛npm中获取
- 构建工具的高度自动化,使得使用npm的成本非常低。
- CommonJS不会异步加载JS,而是同步一次性加载出来。(因为本身是在服务器端运行)
使用
- 需要构建工具支持
- 一般和npm一起用
AMD、CommonJs的使用场景
- 需要异步加载JS,使用AMD
- 使用了npm建议使用CommonJS
构建工具
- grunt
- gulp
- fis3
- webpack
运行环境
- 浏览器可以通过访问链接来得到页面的内容
- 通过绘制和渲染,显示出页面的最终的样子
-
页面加载过程
题目
丛输入url得到html的详细过程
window.onload和DOMContentLoaded的区别
知识点
加载资源的形式
输入url(或页面跳转)加载html
- 加载html中的静态资源,比如css,js,图片,视频等
加载一个资源的过程
- 浏览器根据DNS服务器得到域名的IP地址
- 像这个ip的机器发送http请求
- 服务器收到、处理并返回http请求
-
浏览器渲染页面的过程
根据HTML结构生成DOM tree
- 根据CSS生成CSSOM
- 将DOM和CSSOM整合形成RenderTree
- 根据RenderTree开始渲染和展示
- 遇到script时,会执行并阻塞渲染,(因为js可以修改DOM结构,所以会阻塞,防止冲突)
window.onload和DOMContentLoaded
- window.addEventListener(‘load’)// 页面的全部资源加载完才会执行,包括图片,视频等。
winow.addEventListener(“DOMContentLoaded”) // DOM渲染完成即可执行,此时视频图片可能没有加载完。jquery和zepto,都用这个来判断页面收否已经渲染完,判断zepto是否可以开始执行
性能优化
原则
多使用内存、缓存或者其他方法
-
丛哪里入手
加载页面和静态资源
- 静态资源的合并压缩
- 静态资源缓存
- 使用CDN让资源加载更快
- 使用SSR后段渲染,数据直接输出到HTML中
- 页面渲染
- CSS放前面,JS放后面
- 懒加载
- 减少DOM操作,对DOM查询做缓存
- 减少DOM操作,多个操作尽量合并在一起执行
- document.createDocumnetFragment
- 事件节流
- 需要执行的放到setTimeout,下次执行清楚之前的timeout
- 尽早执行(如DOMContentLoaded)
图片懒加载
- 给图片的src赋值一个小的图片或者固定的图片,自定义属性保存真实路径比如data-realsrc,
- 然后通过JS将真的地址赋值到src
安全性
综合的问题
XSS
主要还是后段来防止
现象
XSRF
主要靠后段来防止
