基础知识
变量类型和计算
题目
- 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 //都转为了false
0 == '' //都转为了false
if语句
逻辑运算符
10 && 0 //0
""||"abc" //"abc"
!window.abc //true
//判断一个变量会被当作true还是false
var 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.elem
if(val){
elem.innerHtml=value;
return this;
}else{
return ele.innerHTML;
}
}
Elem.prototype.on=function(type,fn){
var elem=this.elem
elem.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。在执行前把这些拿出来。
- 注意函数声明和函数表达式。
```javascript
console.log(a) // undefiend
var a=100
fn('zhangsan') // 张三 20
function 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===a
a.fn.call({name:"B"}) // this=== {name:"B"}
var fn1=a.fn
fn1() // this===window
- this要在执行时确认,定义时无法确认。
四种
// 无快级别作用域
if(true){
var name = "zhangsan"
}
console.log(name)
// 等同于
var name
if(true){
name="zhangsan"
}
console.log(name)
// 函数和全局作用域
var a= 100
function fn(){
var a=200
console.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; // 这里的是全局作用域的a
f1()
// 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>
### 日期
```javascript
Date.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
```javascript
var 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.width
screen.height
location
location.href
location.protocol
location.pathname
location.search
location.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
- 另外一个解决跨域的简介方法,需要服务端来做
- 作为交互方,必须知道
- 跨域的趋势
```javascript
const 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.js
define(function () {
return {
getformatedata(){
}
}
})
// a-util.js
define(['./util.js'],function (util) {
return {
getformatedata(data){
return util.getformatedata(data,2)
}
}
})
// a.js
define(['./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
主要靠后段来防止