《前端JavaScript重点》学习笔记 6-12
回顾JS基础知识
- 特点:表面看起来不能用于工作中开发代码。
- 内置函数:Object Array Boolean String ......
- 内置对象:Math JSON
- 我们连网页弹出一句‘hello world’都不能实现
常说的JS包含两部分:
- JS基础知识(ECMA262标准)://规定基础语法、规则
- JS-Web-API(W3C标准)://浏览器需要让开发者做更多事情。例如,如何弹出一个框
JS-Web-API
W3C标准关于JS的规定有
- DOM操作
- BOM操作
- 事件绑定
- ajax请求(包括http协议)
- 存储
JS-Web-API
页面弹框window.alert(123),浏览器需要做:
1)定义一个window全局变量,对象类型
2)给它定义一个alert属性,属性值是一个函数
获取元素document.getElementById(id),浏览器需要做:
1)定义一个document全局变量,对象类型
2)给它定义一个getElementById的属性,属性值是一个函数。
但w3c标准没有规定任何JS基础相关的东西
不管什么变量类型、原型、作用域和异步(这些是ECMA262规定的)
只管定义用于浏览器中JS操作页面的API和全局变量。
全面考虑,JS内置的全局函数和变量有哪些?
1)之前讲过的 Object Array Boolean String Math JSON等
2)刚刚提到的window document
3)接下来要讲的navigator,所有未定义的全局变量
NodeJS包含JS基础知识(ECMA262标准),但不含W3C标准,因为nodeJs不是跑在浏览器的,而是在服务器中。
前端的JS则是二者的集合。
第六篇 DOM和BOM
题目:
1.DOM是哪种基本的数据结构2.DOM操作常用的API有哪些3.DOM节点的attr和property有何区别4.如何检测浏览器的类型5.拆解url的各部分
知识点#####
- DOM本质
DOM(Document Object Model——文档对象模型)是用来呈现以及与任意 HTML 或 XML 交互的API文档。DOM 是载入到浏览器中的文档模型,它用节点树的形式来表现文档,每个节点代表文档的构成部分(例如: element——页面元素、字符串或注释等等)。
DOM可以理解为浏览器把拿到的HTML代码,结构化为一个浏览器能识别并且js可操作的模型。
// HTML是XML的特殊类型
- BOM本质
BOM(Browser Object Document)即浏览器对象模型。
BOM提供了独立于内容 而与浏览器窗口进行交互的对象;
由于BOM主要用于管理窗口与窗口之间的通讯,因此其核心对象是window;
BOM由一系列相关的对象构成,并且每个对象都提供了很多方法与属性; - DOM节点操作
- 获取DOM节点
var div1=document.getElementById('div1') //元素
var divList=document.getElementByTagName('div') //集合
console.log(divList.length);
console.log(divList[0]);
var containerList=document.getElementByClassName('.container') //集合
var pList=document.querySelectorAll('p') //集合
- property
js对象的属性
var pList=document.querySelectorAll('p')var p=pList[0]//获取了DOM对象,对象在js中都是可扩展的console.log(p.style.width); //获取样式p.style.width='100px' //修改样式console.log(p.className); //获取classNamep.className='p1' //修改className//获取nodeName和nodeTypeconsole.log(p.nodeName);console.log(p.nodeType);
- Attribute
标签属性,用于扩充HTML标签,可以改变标签行为或提供数据,格式为name=valuevar pList=document.querySelectorAll('p')var p=pList[0]p.getAttribute('data-name')p.setAttribute('data-name','imooc')p.getAttribute('style')p.setAttribute('style','font-size:30px;')
- DOM结构操作
- 新增节点
var div1=document.getElementById('div1')var p1=document.createElement('p') //创建新节点p1.innerHTML='Hello'div1.appendChild(p1) //添加新创建的元素//移动已有节点var p2=document.getElementById('p2')div1.appendChild(p2)
- 获取父子元素、删除节点
var div1=document.getElementById('div1')var parent=div1.parentElement //获取父元素var child=div1.childNodes //获取子元素div1.removeChild(child[0]) //移除child[0]子节点
- navigator&screen
//navigatorvar ua=navigator.userAgentvar isChrome=ua.indexOf('Chrome')console.log(isChrome);//screenconsole.log(screen.width);console.log(screen.height);
- location&history
//locationconsole.log(location.href); //整个URL路径console.log(location.protocol); //http httpsconsole.log(location.pathname); //域名之后的路径console.log(location.search); //?后的参数console.log(location.hash); //#后的内容
//historyhistory.back()history.forward()
解题#####
1.DOM是哪种基本的数据结构
树
2.DOM操作常用的API有哪些
- 获取DOM节点以及节点的property和Attribute
- 获取父节点,获取子节点
- 新增节点,删除节点
3.DOM节点的attr和property有何区别
- property是一个JS对象的属性的修改
- Attribute是HTML标签属性的修改
4.如何检测浏览器的类型
navigator.userAgent
5.拆解url的各部分
//location
console.log(location.href);
console.log(location.protocol); //协议 http https
console.log(location.pathname); //域名之后的路径
console.log(location.search);
console.log(location.hash);
第七篇 事件
题目:
1.编写一个通用的事件监听函数
2.描述事件冒泡流程
3.对于一个无限下拉加载图片的页面,如何给每个图片绑定事件
知识点#####
- 通用事件绑定
//标准方法 容易写错,var btn=document.getElementById('btn1');btn.addEventListener('click',function(e){console.log('clicked');})//封装事件绑定
function myBindEvent(elem,type,fn){elem.addEventListener(type,fn)}
var a=document.getElementById('link1');myBindEvent(a,'click',function(e){e.preventDefault(); //阻止默认行为alert('link1 has clicked');})IE低版本使用attachEvent绑定事件,和W3C标准不一样IE低版本使用量已非常少,很多网站都早已不支持建议对IE低版本的兼容性:了解即可,无需深究如果遇到对IE低版本要求苛刻的面试,果断放弃
- 事件冒泡
<div id="div1"><p id="p1">激活</p><p id="p2">取消</p><p id="p3">取消</p><p id="p4">取消</p></div><div id="div2"><p id="p5">取消</p><p id="p6">取消</p></div><script type="text/javascript">function myBindEvent(elem,type,fn){elem.addEventListener(type,fn)}var p1=document.getElementById('p1')var body=document.body;myBindEvent(p1,'click',function(e){e.stopPropagation(); //阻止冒泡alert('激活')})myBindEvent(body,'click',function(e){alert('取消');})</script>点击p1,弹出“激活”,如果没有e.stopPropagation(),事件将继续向上冒泡找到body的alert('取消')
- 代理
<div id="div1"><a href="#">a1</a><a href="#">a2</a><a href="#">a3</a><a href="#">a4</a><!-- 会随时新增更多a标签 --></div><script type="text/javascript">function myBindEvent(elem,type,fn){elem.addEventListener(type,fn)}var div1=document.getElementById('div1')myBindEvent(div1,'click',function(e){ //通过事件冒泡机制var target=e.target //获取要绑定事件的元素if(target.nodeName==='A'){alert(target.innerHTML)}})</script>点击每一个a标签弹出对应的标签内的内容
解题#####
1.编写一个通用的事件监听函数
//仅有这种情况使用'=='
if(obj.a==null){
//此时条件相当于obj.a===null||obj.a===undefined,简写形式
//这是jQuery源码中推荐的写法
}
function myBindEvent(elem,type,selector,fn){
if(fn==null){
fn=selector;
selector=null;
}
elem.addEventListener(type,function(e){
var target;
if(selector){
// 代理
target=e.target;
if(target.matches(selector)){ //判断目标节点是否和选择器匹配
fn.call(target,e); //target被当做fn函数中的this
}
}else{
// 不使用代理
fn(e);
}
})
}
//mathes() 用来判断当前DOM节点能否完全匹配对应的CSS选择器规则;如果匹配成功,返回true,反之则返回false。
//使用代理
var div1=document.getElementById('div1');
myBindEvent(div1,'click','a',function(e){
e.preventDefault();
console.log(this.href);
})
//不使用代理
var btn1=document.getElementById('btn1');
myBindEvent(btn1,'click',function(e){
console.log(btn1.innerHTML);
})
//上一篇知识点:call apply bind
function fn1(name,age){
alert(name)
console.log(this)
}
fn1.call({x:100},'zhangsan',20) //({x:100}
代理的好处:
- 代码简介 (不用写那么多绑定)
- 减少浏览器内存占用 (绑定一次浏览器累积一次)
2.描述事件冒泡流程
- DOM树形结构
- 事件冒泡
- 阻止冒泡
3.对于一个无限下拉加载图片的页面,如何给每个图片绑定事件
使用代理
第八篇 存储与Ajax
1.请描述一下cookie,sessionStorage,和localStorage的区别2.手动编写一个ajax,不依赖第三方库3.跨域的几种实现方式
知识点#####
- cookie
- 本身用于客户端服务端通信,但它有本地存储的功能于是就被‘借用’,使用documen.cookie=...获取和修改
- 缺点:
- 存储量太小,只有4kb
- 所有http请求都带着,会影响获取资源的效率
- API简单,需要封装才能用,document.cookie=...用起来麻烦
- localStorage和sessionStorage(这两者在HTML5出现之后才出现)
- HTML5专为存储设计,最大容量5M(不用在http请求中携带)
- API:localStorage.setItem(key,value); localStorage.getItem(key); // sessionstorage也是setItem(),getItem().
- IOS Safari隐藏模式下,localStorage.getItem(key);会报错,建议同意使用try-catch封装
- 区别:localstorage可以存储在本地,sessionStorage在浏览器关闭时就会清理。因此多用localstorage。
- cookie sessionStorage localStorage区别
- 容量区别,cookie为4k,localStorage和sessionStorage为5M
- cookie每次请求都会被携带在ajax中,localStorage和sessionStorage不会被携带只作为存储使用
- API易用性 cookie自己封装一大段代码,后两个用两个API基本满足需求
- XMLHttpRequest
var xhr=new XMLHttpRequest();xhr.open('GET','/api',false)xhr.onreadystatechange=function(){//这里的函数异步执行if(xhr.readyState==4){if(xhr.status==200){alert(xhr.responseText)}}}xhr.send(null)
IE低版本使用ActiveXObject,和W3C标准不一样
IE低版本使用量已非常少,很多网站都早已不支持
建议对IE低版本的兼容性:了解即可,无需深究
如果遇到对IE低版本要求苛刻的面试,果断放弃
- 状态码说明
- readyState
- 0-(未初始化)还没有调用send()方法
- 1-(载入)已调用send()方法,正在发送请求
- 2-(载入完成)send()方法执行完成,已经收到全部响应内容
- 3-(交互)正在解析响应内容
- 4-(完成)响应内容解析完成,可以在客户端调用了
- status
- 2xx-成功处理请求。如200
- 3xx-需要重定向,浏览器直接跳转
- 4xx-客户端请求错误,如404(地址错误)
- 5xx-服务器端错误
- 跨域
- 什么是跨域
- 浏览器有同源策略,不允许ajax访问其他域接口
协议:http/https;
域名:www.yourname.com/m.imooc.com
端口:8080/80 不写时使用默认值
- 跨域条件:协议、域名、端口,有一个不同就算跨域
- 可以跨域的三个标签:
- <img src=''>
- <link href=''>
- <script src=''>
- 三个标签的场景
- <img> 用于打点统计,统计网站可能是其它域
- <link><script>可以使用CDN,CDN也是其它域
- <script>可以用于JSONP,马上讲解 //JSONP就是利用<script>的src来实现跨域获取数据的。
- 跨域注意事项
- 所有的跨域请求都必须经过信息提供方的允许
- 如果未经允许即可获取,那就是浏览器的同源策略出现漏洞
- 方式一:JSONP
加载http://coding.m.imooc.com/classindex.html,不一定服务器端真的有一个classindex.html文件,服务器可以根据请求动态生成一个文件来返回,同理于<script src='http://coding.m.imooc.com/api.js'>; - 实现原理
假如你的网站要跨域访问慕课网的一个接口,慕课网给你一个地址http://coding.m.imooc.com/api.js,返回内容格式如callback({x:100,y:200})(可动态生成)
<script>window.callback=function(data){//这是我们跨域得到的信息console.log(data);}</script><script src='http://coding.m.imooc.com/api.js';></script><!-- 以上将返回callback({x:100,y:200}) -->补充:JSONP 是 JSON with padding(填充式 JSON 或参数式 JSON)的简写。JSONP实现跨域请求的原理简单的说,就是动态创建<script>标签,然后利用<script>的src 不受同源策略约束来跨域获取数据。JSONP 由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数。回调函数的名字一般是在请求中指定的。而数据就是传入回调函数中的 JSON 数据。动态创建<script>标签,设置其src,回调函数在src中设置:var script = document.createElement("script");document.body.insertBefore(script, document.body.firstChild);在页面中,返回的JSON作为参数传入回调函数中,我们通过回调函数来来操作数据。function handleResponse(response){// 对response数据进行操作代码}
了解了JSONP的基本使用方法,我们在实现上面通过ajax调用豆瓣接口的需求,实现代码如下:<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>JSONP实现跨域2</title></head><body><div id="mydiv"><button id="btn">点击</button></div></body><script type="text/javascript">function handleResponse(response){console.log(response);}</script><script type="text/javascript">window.onload = function() {var oBtn = document.getElementById('btn');oBtn.onclick = function() {var script = document.createElement("script");document.body.insertBefore(script, document.body.firstChild);};};</script></html>
- 方式2:服务端设置http header
另外一个解决跨域的简单方法,需要服务器端来做,但是作为交互方,我们必须知道这个方法,是将来解决跨域问题的一个趋势//注意:不同后端语言的写法可能不一样//第二个参数填写允许跨域的域名称,不建议直接写"*"response.setHeader('Access-Control-Allow-Origin','http://a.com,http://b.com';);response.setHeader('Access-Control-Allow-Headers','X-Request-With');response.setHeader('Access-Control-Allow-Methods','PUT,POST,GET,DELETE,OPTIONS');//接收跨域的cookie
response.setHeader('Access-Control-Allow-Credentials','true');
- 方式3:iframe //自己添加的
解题#####
1.请描述一下cookie,sessionStorage,和localStorage的区别
- 容量区别,cookie为4k,localStorage和sessionStorage为5M
- cookie每次请求都会被携带在ajax中,localStorage和sessionStorage不会被携带只作为存储使用
- API易用性 cookie自己封装一大段代码,后两个用两个API基本满足需求
2.手动编写一个ajax,不依赖第三方库
var xhr=new XMLHttpRequest()
xhr.open('GET','/api',false)
xhr.onreadystatechange=function(){
//这里的函数异步执行
if(xhr.readyState==4){
if(xhr.status==200){
alert(xhr.responseText)
}
}
}
xhr.send(null) //get请求时为空或null,post请求时参数为要发送的数据。
3. 跨域的几种实现方式
- JSONP
- 服务器端设置http header
作者:Yangkeloff
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
第九篇 开发环境
关于开发环境:
1)面试官想通过开发环境了解面试者的经验
2)开发环境最能体现工作产出的效率
3)会以聊天的形式为主,而不是具体的问题
- IDE(写代码的效率)
- git(代码版本管理,多人协作开发)
- JS模块化
- 打包工具
- 上线回滚的流程
- IDE
- webstorm sublime vscode atom 插件
- 不要说自己使用Dreamweaver、notepad
- git
- 正式项目都需要代码版本管理
- 大型项目需要多人协作开发
- Git和Linux是同一个作者
- 网络Git服务器如coding.net、github.com
- 一般公司代码非开源,都有自己的Git服务器
- 搭建Git服务器无需了解太多
- Git的基本操作必须很熟练
- 常用Git命令
- git add .
- git checkout xxx //切换到已有的分支
- git commit -m "xxx"
- git push origin master //提交到远程仓库
- git pull origin master //从仓库下载
- git branch //查看所有分支
- git checkout -b xxx / git checkout xxx //新建一个分支 /切换到已有的分支
- git merge xxx // 把xxx分支合并到当前分支
- 代码演示
9-1 JS模块化
模块化本身就是一个面试的问题
知识点#####
- 不使用模块化的情况
函数
调用1.js文件引入顺序必须遵循函数层级引用的顺序,最先引入util.js,然后a-util.js,以此类推2.这些代码中的函数必须是全局变量,才能暴露给使用方,会有全局变量污染的问题3.a.js知道要引用a-util.js,但是它并不知道还依赖于util.js,代码逻辑并不清晰,所以要使用模块化
- 使用模块化
1.直接使用<script type="text/javascript" src="a.js"></script>即可,其它会根据依赖关系自动引用2.在util.js和a-util.js中没有使用全局变量,不会带来污染和覆盖3.以上代码只是理想中的效果,用于描述模块化的思想,和实际语法相比略有出入
- AMD
- A:异步 M:模块 D:定义
- require.js <a>requirejs.org</a>
- 全局define函数
- 全局require函数
- 依赖JS会自动异步加载
- 使用requirejs完成刚才的例子
//util.jsdefine(function(){var util={getFormatDate:function(date,type){if(type===1){var month=date.getMonth()+1;var day=date.getDate();if(month<10){month='0'+month;}if(day<10){day='0'+day;}return date.getFullYear()+'-'+month+'-'+day;}if(type===2){return date.getFullYear()+'年'+(date.getMonth()+1)+'月'+date.getDate()+'日';}}}return util;})//a-util.jsdefine(['./util.js'],function(util){var aUtil={aGetFormatDate:function(date){return util.getFormatDate(date,2)}}return aUtil})//a.jsdefine(['./a-util.js'],function(aUtil){var a={printDate:function(date){console.log(aUtil.aGetFormatDate(date));}}return a;})//main.jsrequire(['./js/a.js'],function(a){var date=new Date()a.printDate(date)})//html<script data-main="./js/main.js" src="https://cdn.bootcss.com/require.js/2.3.3/require.min.js";></script>
- CommonJS
- CommonJS是Nodejs模块化规范,现在被大量用前端
- 前端开发依赖的插件和库,都可以从npm获取
- 构建工具高度自动化,使npm成本非常低
- CommonJS本身不会异步加载JS,而是一次性同步加载出来
- module.exports={aaa:...,bbb:...}输出模块,require(xxx.js)引用模块
- 使用CommonJS
// util.jsmodule.exports={getFormatDate:function(date,type){if(type===1){var month=date.getMonth()+1var day=date.getDate()if(month<10){month='0'+month;}if(day<10){day='0'+day;}return date.getFullYear()+'-'+month+'-'+day}if(type===2){return date.getFullYear()+'年'+(date.getMonth()+1)+'月'+date.getDate()+'日'}}}//a-tuil.jsvar util=require('util.js')module.exports={aGetFormatDate:function(date){return util.getFormatDate(date,2)}}commonJS 暴露给外部的接口为module.exports 所指向的对象,而AMD 暴露给外部的接口为return 的对象
- AMD和CommonJS的使用场景
- 需要异步加载,使用AMD
- 使用npm后建议使用CommonJS(需要异步加载,使用CommonJS)
9-2 构建工具
- webpack
使用
首先,启动一个服务器,接着初始化npm环境,然后安装webpack
1)进入当前文件目录2)npm install http-server -g3)http-server -p 8881 //启动服务器 只能浏览静态网页 。http-server是常用的轻量级web服务器4)初始化npm环境 npm init //生成package.json文件5)npm install webpack --save-dev // 安装开发版本的webpack。生成了node-moudles文件夹--save //保存在package.json中,不加--save表示只安装不保存在package.json-dev //安装开发版本npm install moment --save//安装非开发版的方法npm unstall moment --save //卸载npm的方法看下图注意开发版和非开发版的区别
//新建文件 webpack.config.jsvar path=require('path');var webpack=require('webpack');module.exports={context:path.resolve(__dirname,'./src'), //找到src目录 ( 自己创建scr)entry:{ //入口,在src下app:'./app.js' //(自己创建app.js )},output:{path:path.resolve(__dirname,'./dist'), //输出至dist目录 (会自动生成)filename:'bundle.js' //输出文件名 (会自动生成)},plugins:[new webpack.optimize.UglifyJsPlugin() //代码压缩]}//package.json{"name": "webpack-test","version": "1.0.0","description": "webpack test","main": "index.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1","start": "webpack" //新添加,用于启动},"author": "liuxin","license": "ISC","devDependencies": {"webpack": "^3.10.0"},"dependencies": {"jquery": "^3.3.1"}}//app.jsconsole.log(1)命令行执行: npm start //在本地配置一个服务器环境,npm start首先会安装一系列的必要程序,这些程序依赖package.json中的内容。输出
生成webpack.config.js中指定的文件夹和文件
将bundle.js引入index.html中//index.html<body><div id="root"></div><script src="dist/bundle.js"></script></body>命令行执行 http-server -p 8881 启动服务器控制台输出 1构建工具--使用jQuery//hello.jsmodule.exports={print:function(){console.log('hello');}}//app.jsvar $=require('jquery'); //调用npm安装的jQueryvar hello=require('./hello.js');var $root=$('#root');$root.html('<p>这是jquery插入的恩子</p>');hello.print();重新npm start,执行。运行结果:补充:http-server 超轻量级web服务器有的时候做前端,想要运行一些代码,但是又没有必要使用tomcat或者Apache http server,这个时候一个轻量级的简单的http server就可以搞定了。Http-server是基于nodejs的http服务器,它最大好处就是:可以使任意一个目录成为服务器的目录,完全抛开后台的沉重工程,直接运行想要的js代码。
- 上线和回滚
知识点
- 上线和回滚的基本流程
- Linux基本命令
上线和回滚流程:
1)非常重要的开发环节
2)各个公司的具体流程不同
3)由专门的工具或者系统完成,我们无需关心细节
4)如果你没有参与过,面试时也要说出要点
5)只讲要点,具体实现无法讲解
上线流程要点:
1)将测试完成的代码提交到git版本库的master分支
2)将当前服务器的代码全部打包并记录版本号,备份
3)将master分支的代码提交覆盖到线上服务器,生成新版本号
回滚流程要点:
1)将当前服务器的代码打包并记录版本号,备份
2)将备份的上一个版本号解压,覆盖到线上服务器,并生成新的版本号
Linux基本命令---使用原因
1)服务器使用Linux居多,server版,只有命令行
2)测试环境要匹配线上环境因此也是Linux
3)经常需要登录测试机来自己配置、获取数据
Linux基本命令
mkdir a //创建文件夹a
ll //查看当前文件
cd a //进入文件夹a
pwd // 查看当前目录/路径
cd.. //返回上层目录
rm -rf a //删除文件夹a
vi a.js //或者vim。表示编辑。创建a.js文件并打开编辑器,按下I 表示输入模式,可以编辑代码。 退出按ESC,退出保存按ESC键+W键。:+w 保存。: + q 退出。 :+w+q 保存后退出
cp a.js a1.js //拷贝a.js到a1.js
mkdir src
mv a1.js src/aj.js //移动a1.js到src下
cat a.js //在命令行打印a.js内容
head a.js //在命令行打印a.js前一部分的内容
tail a.js //在命令行打印a.js后一部分的内容
head -n 1 a.js //在命令行打印a.js第一行
tail -n 2 a.js //在命令行打印a.js最后两行
grep '2' a.js //搜索第二行内容 打印
第十篇 页面加载与性能优化
1.从输入url到得到HTML的详细过程 (常考)2.window.onload和DOMContentLoaded的区别3.性能优化的几个示例
知识点#####
- 加载资源的形式
- 输入url(或跳转页面)加载HTML http://xxxxx.com
- 加载HTML中的静态资源 如js css 图片 视频 媒体资源等
- 加载一个资源的过程
- 浏览器根据DNS服务器(域名服务器)得到域名的IP地址 (得到baidu.com的IP地址)
- 向这个IP的机器发送http请求
- 服务器收到、处理并返回http请求(可能是js css HTML 图片等文件)
- 浏览器得到返回内容
- 浏览器渲染页面的过程
- 根据HTML结构生成DOM Tree
- 根据CSS生成CSSOM
- 将DOM和CSSOM整合成RenderTree(渲染树:比dom tree多了样式)
- 根据RenderTree渲染和展示
- 遇到<script>时,会执行并阻塞渲染,所以<script>放在<body>即将结束的位置 因为js有权利改变dom结构,如果同时进行会发生冲突
思考:1.为何把css放在head中
2.为何把js放在body最下面。 1)不会阻塞页面的渲染,让页面更快出来 2)script能拿到所有标签,放在上面时拿不到
- window.onlaod和DOMContentLoaded
window.addEventListerer('load',function(){//页面的全部资源加载完才会执行,包括图片、视频等})window.addEventListerer('DOMContentLoaded',function(){//DOM渲染完即可执行,此时图片、视频等可能还没加载完})
- 性能优化
- 原则
- 多使用内存、缓存或其他方法;
- 减少CPU计算和网络请求
- 从哪里入手
- 加载页面和静态资源
- 页面渲染
- 优化方法
//加载资源优化 加载页面和静态资源
- 静态资源的压缩合并(如webpack的plugins:[new webpack.optimize.UglifyJsPlugin()])
- 静态资源缓存 (如浏览器第一次请求过后,第二次就不用再次请求了。这是浏览器的优化策略)
- 使用CDN让资源加载更快 (大网站都有自己的cdn。比如加载jQuery,会从就近的机房加载,否则只能同较远的服务器请求)
- 使用SSR(server side rendering)后端渲染(服务端),数据直接输出到HTML (比如最早时候用jsp、PHP、asp写页面时,本身就是后端渲染,数据直接输出到HTML,不是现在的先写HTML再用ajax请求把数据拿过来)
//渲染优化。 页面渲染
- CSS放前面,JS放后面
- 懒加载(图片懒加载、下拉加载更多)
- 减少DOM查询,对DOM查询做缓存
- 减少DOM操作,多个操作尽量合并在一起执行
- 事件节流 (下面的实例)
- 尽早执行操作(如DOMContentLoaded)
- 安全性
解题#####
1.从输入url到得到HTML的详细过程
- 浏览器根据DNS服务器得到域名的IP地址
- 向这个IP的机器发送http请求
- 服务器收到、处理并返回http请求
- 浏览器得到返回内容并渲染页面
2.window.onload和DOMContentLoaded的区别
window.onload,页面的全部资源加载完成才会执行,包括图片视频等
DOMContentLoaded,DOM渲染完即可执行,此时图片视频等可能还没加载完
补充:$(function(){})在window.onload执行前执行的,$(function(){})类似于原生js中的DOMContentLoaded事件,在DOM加载完毕后,页面全部内容(如图片等)完全加载完毕前被执行。而window.onload会在页面资源全部加载完毕后才会执行。
3.性能优化的几个示例
- 合并js文件,减少请求次数
- 缓存:比如通过连接名称控制缓存<script src="abc_1.js"></script>只有内容改变时才更改名称<script src="abc_2.js"></script>
- 使用CDN<script src="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"></script>;
- 使用SSR后端渲染:现在(Vue、React)提出了这样的概念,
- 懒加载
//给src赋值一个很小的图片或者缓存的图片,但真正的图片是 abc.png,通过js来控制<img id="img1" src="prview.png" data-realsrc="abc.png"/><script type="text/javascript">var img1=document.getElementById('img1')img1.src=img1.setAttribute('data-realsrc')</script>
- 缓存DOM查询
var x=document.getElementBy... //这样可以避免多次执行DOM查询
- 合并DOM插入
var listNode=document.getElementById('list')//插入10个li标签var frag=document.createDocumentFragment();var x,lifor(x=0;x<10;x++){li=document.createElement('li')li.innerHTML='List item'+xfrag.appendChild(li)}listNode.appendChild(frag) //只进行了一次dom操作
- 事件节流
在快速操作时不执行事件,在停顿时执行,以减少计算次数
var textarea=document.getElementById('text')var timeoutIdtextarea.addEventListener('keyup',function(){if(timeoutId){clearTimeout(timeoutId)}timeoutId=setTimeout(function () {//触发change事件}, 100); //停顿100ms以上才触发changge事件})
- 尽早操作
window.addEventListener('load',function(){//页面的全部资源加载完成才会执行,包括图片视频等})document.addEventListener('DOMContentLoaded',function(){//DOM渲染完即可执行,此时图片视频等可能还没加载完})
第十一篇 安全性
知识点#####
安全性在前端面试中的概率是比较低的。有专门的安全人员,一般后端来做。一下列出两种常见的前端攻击方式,主要还是靠后端来解决,前端做一些接口性的配合等。
- XSS跨站请求攻击
新浪博客写一篇文章,同时偷偷插入一段<script>,
攻击代码中,有获取cookie,发送到自己的服务器的代码,
发布文章被人查看,会把查看者的cookie发送到攻击者的服务器
//cookie包含有账户等信息,可能有密码等机密信息
- 解决
- 前端替换关键字,如替换<为<,替换>为>。但前端效率低
- 后端替换
- XSRF跨站请求伪造
已登录一个网站正在浏览商品,该网站付费接口是xxx.com/pay?id=100,但是没有任何验证,然后你收到了一封邮件,隐藏着![](xxx.com/pay?id=100),当查看邮件时就已完成付费了 - 解决
- 增加验证流程,如输入指纹,密码,短信验证码 //也是后端验证,前端配合
第十二篇 面试技巧
技术岗面试技巧不是很多,主要考核的是面试者的技术能力,如果过于注重技巧会有些喧宾夺主的感觉
- 简历
- 简洁明了,重点突出项目经历和解决方案
- 把个人博客放在简历中,并且定期维护更新博客
- 把个人的开源项目放在简历中,并维护开源项目
- 简历千万不要造假,要保持能力和经历上的真实性
- 面试过程中
- 如何看待加班?加班就像借钱,救急不救穷
- 千万不可挑战面试官,不要反考面试官
- 学会给面试官惊喜,但不要太多
- 遇到不会回答的问题,说出你知道的也可以
- 谈谈你的缺点——说一下你最近正在学的东西就可以了 (正在学习react,但不是很熟练,大概再过多久就能熟练掌握)