本次主要搬运神策数据公司以及其他面试的常问问题
① Link标签的href属性
② Script标签的src属性
③ Img标签的src属性
④ Ajax发送请求
⑤ 表单提交发送请求
⑥ a标签的href属性
⑦ Iframe的src属性
<div>
<ul>
</ul>
</div>
<style>
div {
background-color: pink;
}
</style>
<script>
let ul = document.querySelector('ul'); //获取父元素
let li = document.createElement('li'); //获取子元素
li.innerText = '子元素'; //给子元素添加文字
ul.appendChild(li) //插入到父元素中
</script>
GET和POST,两者是HTTP协议中发送请求的方法
GET
GET方法请求一个指定资源的表示形式,使用GET的请求应该只被用于获取数据
POST
POST方法用于将实体提交到指定的资源,通常导致在服务器上的状态变化或副作用
本质上都是TCP链接,并无差别
但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中会体现出一些区别
(这里也可以用promise.all)
要求:异步函数之间有关联关系;前一个异步函数的输出作为后一个异步函数的输入;
在做异步函数之间有关联关系之前,先来做一下同步函数的执行,前面一个同步函数的输出作为后面一个同步函数的输入
const add = x => x + 5;
const multiply = (x) => x * 5;
const subtraction = x => x - 5;
const division = x => x / 5;
const targetFn = pipeFunctions(
add, //10
multiply, //50
subtraction, //45
division //9
);
targetFn(5);
我们执行 targetFn希望最后的结果是9,那么这个 pipeFunctions该怎么实现呢?
pipeFunctions会接收参数,但是我们也不知道有多少个,所以使用扩展运算符。前一轮结束的结果作为下面一个的输入,我们可以采用reduce方法(reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。)reduce函数有四个参数
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
| 参数 | 含义 |
|---|---|
| total 必需 | 初始值, 或者计算结束后的返回值。 |
| currentValue | 必需。当前元素 |
| currentIndex | 可选。当前元素的索引 |
| arr | 当前元素所属的数组对象。 |
我们这个里面的reduce接收的第一个参数是一个回调函数,第二个是回调函数的初始值,此时我们的参数为(preFn,curFn),preFn表示上一轮函数,比如我们的add,curFn表示当前的函数。在这个方法里面,他是需要函数调用的,所以就需要返回一个函数,因为我们要在函数里面执行,而且下一轮的结果也是一个函数。这个函数同样我们也不知道参数是多少个,所以也要给一个扩展运算符。接下来要执行这个函数,将上一轮的函数执行res = preFn(…args),得到上一轮的结果res,再将这个结果放到当前执行。做成了一个链式调用的效果。
// reduce
fns.reduce((preFn, curFn) => {
return (..args) => {
const res = preFn(...args);
return curFn(res);
};
};
整体代码如下:
const add = x => x + 5;
const multiply = (x) => x * 5;
const subtraction = x => x - 5;
const division = x => x / 5;
const pipeFunctions = (...fns) => {
// reduce
return fns.reduce((preFn, curFn) => {
return (...args) => {
const res = preFn(...args);
return curFn(res);
};
})
}
const targetFn = pipeFunctions(
add,
multiply,
subtraction,
division
);
console.log(targetFn(5)); //9
异步的话:
//异步
//模拟一下异步的随机的时间戳,代表异步执行的时间
const asyncFn = (v) => {
return new Promise(resolve => {
setTimeout(() => {
resolve(v);
}, Math.random() * 1000);
});
};
const add2 = async x => await asyncFn(x + 5);
const multiply2 = async(x) => await asyncFn(x * 5);
const subtraction2 = async x => await asyncFn(x - 5);
const division2 = async x => await asyncFn(x / 5);
const targetFn2 = pipeFunctions2(
add2,
multiply2,
subtraction2,
division2
);
targetFn2(5); //9
这里最关键的就是对于pipeFunctions2函数的编写,它的参数同样是不定的,同样使用reduce方法,参数同上。返回的时候是需要对preFn执行的,preFn它还是一个异步函数,所以我们返回的时候要加上async

Script标签引入方式:4种
1.script的标签
<script>
var str1 = "123";
console.log(str1);//控制台打印
</script>
2.a标签引入
<a href="javascript:alert('hah')">sdfsdf</a>
3.div后面引入
<div onclick="alert('我被点击了')"></div>
//直接在后面写点击事件
4.script引入JS文件
<script src="js/nihao.js"></script>
方法一,在调用文件的顶部加入下例代码
document.createElement("script").setAttribute("src", "render.js");
方法二,在调用文件的顶部加入下例代码
function addScript(url){
document.write("< script language=javascript src="+url+"> script>");
}
方法三,在js中写如下代码:
function addScript(url){
var script = document.createElement('script');
script.setAttribute('type','text/javascript');
script.setAttribute('src',url);
document.getElementsByTagName('head')[0].appendChild(script);
}
利用document.createElement(”script”)生成了一个script的标签,设置其 type属性text/javascript。
方法四,利用es6中export和import实现模块化
一个js文件代表一个js模块 。ES6引入外部模块分两种情况:
1.导入外部的变量或函数等;
import {firstName, lastName} from './test';
2.导入外部的模块,并立即执行
import './test' //执行test.js,但不导入任何变量
详情参考:js文件中引入js的方法
看功能和触发方式,异步请求处理必要性高的,使用 promise 处理关联性强的,非必要接口懒加载,散碎的最好让后端进行接口整合,也可以用 promiseall 来处理,交互性接口考虑截流和防抖,避免重复加载,交互密集度高的可以考虑使用长连接或者 socket,展示数据根据需求考虑预先加载进行本地缓存。
还可以考虑


那升级之前,可以把50个请求变成10个请求吗?
我说:可以

做一个中间件,将5个请求合并为1个请求。50个请求就会变成10个请求。将请求集成。或者和后端去沟通,去把接口优化
有的,CHROME浏览器发送HTTP最大请求并发数限制
①同一域名下,同一GET请求的并发数是1,也就是说上一个请求结束,才会执行下一个请求,否则置入队列等待发送;
②同一域名下,不同GET/POST请求的并发数量是6。当发送的请求数量达到6个,并且都没有得到响应时,后面的请求会置入队列等待发送。
如何分析页面加载慢?
我知道有分析加载js文件和css文件时间的工具,可以通过这个工具去看哪类文件的问题
老师说:其实控制台就可以看到
解决方案,第一个路由懒加载
第二个 js文件放到底部
老师追问:放到底部,如果js文件里有大量的计算,还会阻塞界面吗
我说:会
老师问:那怎么解决,
我说:异步记载,
老师说:还有没有其他方案,我没答上来。他说,js是单线程,可以考虑在开一个线程专门加载js文件,比如webWorker,这个你下去可以再学一下
网路请求还可以优化吗
我回答:内容分发网络(CDN)
注:内容分发网络的原理:
通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络,CDN 系统能够实时地根据 网络流量 和 各节点的连接、负载状况 以及 到用户的距离 和 响应时间 等综合信息将用户的请求重新导向离用户最近的服务节点上。比如:

前端性能优化-优化大量图片加载&超大图片加载(附懒加载实现方案)
promise和generator主要都是处理异步请求,如果访问的内容元素固定,两者写法类似,其差别不大。Promise适合一次读一堆固定格式的数据,generator适合读具有逻辑性的数据。
可以用媒体查询。
可以使用rem或者vh、vw相对单位
rem相对于body标签的字体大小,如果body的font-size:16px;那么1rem = 16px
相对于父级元素。(当时答错了!)
flex与grid是css3新增的布局属性。分别为了解决:一维与二维的布局缺陷。
flex存在两条轴:水平主轴、竖直交叉轴。
默认项目不换行在主轴上水平排列,可以使用flex-direction: column;使其竖直排列。
key可以体改虚拟dom的更新效率。
在vue中默认“就地复用”的策略,在DOM操作时,如果没有key就会造成选项错乱。
key只能是字符串或者num;
SPA单页面应用(SinglePage Web Application) ,指只有一个主页面的应用(一个html页面),一开始只需要加载一次js、css的相关资源。所有内容都包含在主页面,对每一个功能模块组件化。单页应用跳转,就是切换相关组件,仅仅刷新局部资源。
MPA多页面应用(MultiPage Application) ,指有多个独立页面的应用(多个html页面),每个页面必须重复加载js、css等相关资源。多页应用跳转,需要整页资源刷新。


var a = 10;
function f(){};
console.log(window.a); // 10
console.log(window.f); // f(){}
但是
let a = 1;
const b = 2;
console.log(window.a); // undefined
console.log(window.b); // undefined

通过上图也可以看到,在全局作用域中,用 let 和 const 声明的全局变量并没有在全局对象中,只是一个块级作用域(Script)中。
结论:
使用 let / const 声明的全局变量,会被绑定到Script对象而不是Window对象,不能以Window.xx 的形式使用;使用 var 声明的全局变量会被绑定到Window对象;使用var / let / const 声明的局部变量都会被绑定到 Local 对象。注:Script对象、Window对象、Local对象三者是平行并列关系。
JavaScript中的global对象,window对象以及document对象的区别和联系
bind和call、apply有什么作用?它们的区别是什么?
浏览器缓存的全过程:
利用函数节流实现监听滚动条停止.函数节流的基本思想是设置一个定时器,在指定时间间隔内运行代码时清楚上一次的定时器,并设置另一个定时器,直到函数请求停止并超过时间间隔才会执行。
| 序号 | 方法 | 描述用途 |
|---|---|---|
| 1 | GET | 【获取资源】本质就是发送一个请求来取得服务器上的某一资源。资源通过一组HTTP头和呈现数据(如HTML文本,或者图片或者视频等)返回给客户端。GET请求中,永远不会包含呈现数据。 即GET请求只用来向服务器获取资源,而GET请求本身不应该携带任何呈现数据。1. 登录时GET获取服务器数据库用户名和密码进行验证。2.下载文本、图片、音视频等时获取服务器资源。 |
| 2 | POST | 【传输实体文本】向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在POST请求体中。POST 请求可能会导致新的资源的建立或已有资源的修改。1. 提交用户注册信息。2. 提交修改的用户信息。 |
| 3 | HEAD | 【获得报文首部】类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头。欲判断某个资源是否存在,我们通常使用GET,但这里用HEAD则意义更加明确。1. 向服务器获取某些易过期或丢失大型文件时,可用HEAD方式查询资源是否存在。 |
| 4 | OPTIONS | 【询问支持的方法】客户端询问服务器可以提交哪些请求方法。这个方法很有趣,它用于获取当前URL所支持的方法。若请求成功,则它会在HTTP头中包含一个名为“Allow”的头,值是所支持的方法,如“GET, POST”。极少使用。 |
| 5 | PUT | 【传输文件】从客户端向服务器传送的数据取代指定的文档的内容,即指定上传资源存放路径。这个方法比较少见。HTML表单也不支持这个。本质上来讲, PUT和POST极为相似,都是向服务器发送数据,但它们之间有一个重要区别,PUT通常指定了资源的存放位置,而POST则没有,POST的数据存放位置由服务器自己决定。如一个用于提交博文的URL,/addBlog。如果用PUT,则提交的URL会是像这样的”/addBlog/abc123”,其中abc123就是这个博文的地址。而如果用POST,则这个地址会在提交后由服务器告知客户端。目前大部分博客都是这样的。显然,PUT和POST用途是不一样的。具体用哪个还取决于当前的业务场景。 |
| 6 | PATCH | 【局部更新文件】是对 PUT 方法的补充,用来对已知资源进行局部更新 。极少使用。 |
| 7 | DELETE | 【删除文件】请求服务器删除指定的资源。基本上这个也很少见,不过还是有一些地方比如amazon的S3云服务里面就用的这个方法来删除资源。 |
| 8 | TRACE | 【追踪路径】回显服务器收到的请求,客户端可以对请求消息的传输路径进行追踪,TRACE方法是让Web服务器端将之前的请求通信还给客户端的方法。主要用于测试或诊断。极少使用。 |
| 9 | CONNECT | 【要求用隧道协议连接代理】HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。CONNECT方法要求在与代理服务器通信时建立隧道,实现用隧道协议进行TCP通信。主要使用SSL(安全套接层)和TLS(传输层安全)协议把通信内容加密后经网络隧道传输。极少使用。 |
webpack 本身只能处理 JavaScript 和 JSON 文件,而 loader 为 webpack 添加了处理其他类型文件的能力。loader 将其他类型的文件转换成有效的 webpack modules(如 ESmodule、CommonJS、AMD),webpack 能消费这些模块,并将其添加到依赖关系图中。
loader 本质上是一个函数,该函数对接收到的内容进行转换,返回转换后的结果。
常见的 loader 有:
使用 loader 的方式主要有两种:
module.exports = {
module: {
rules: [{ test: /\.ts$/, use: "ts-loader" }],
},
};
import Styles from "style-loader!css-loader?modules!./styles.css";
Loader 的输入和输出:
输入:
/**
* @param {string|Buffer} content 源文件的内容
* @param {object} [map] 可以被 https://github.com/mozilla/source-map 使用的 SourceMap 数据
* @param {any} [meta] meta 数据,可以是任何内容
*/
function loader(content, map, meta) {
}
Loader 的输出?
loader 的返回的结果应该是 String 或者 Buffer 类型(可以被转成 String 类型)。
对于最后一个 loader 而言,其结果代表了模块的 JavaScript 源码,即 JavaScript 代码字符串。这个结果会传给 Webpack Compiler 进行下一步的处理。
手写一个 Webpack Loader
SASS(英文全称:Syntactically Awesome Stylesheets)Sass 诞生于 2007 年,使用Ruby 编写,是一种对css的一种扩展提升,增加了规则、变量、混入、选择器、继承等等特性。可以理解为用js的方式去书写,然后编译成css。比如说,sass中可以把反复使用的css属性值定义成变量,然后通过变量名来引用它们,而无需重复书写这一属性值。
1、css中的图片以背景图形式存在,写在html中的图片以标签形式存在。而在网页加载过程中,以css背景存在的图片会等到html结构加载完成才开始加载,而html中的img标签是网页结构(内容)的一部分会在加载结构的过程中加载。
附:在一个单纯由Html和Css组成的页面中,背景图片总是最后加载的,那么假若我们想要使用较小的背景图片作为占位符,用于在加载较大的图片或者Flash文件时给用户以提示,大部分时候恐怕是达不到效果的,因为背景图片有时甚至会在大图片或Flash文件加载完成之后才会被加载。
2、通常非内容的图片(即用来修饰页面的元素)就写在css里,如果是内容性的图片就写在html中。比如,你要做一个漂亮相框的相册,那么修饰边框的图片就写在css里,相框里的内容照片就写在html中。
3、图片作为背景,在图片没有加载或者加载失败时,不会有个图片的占位标记,不会出现红叉。
script 是会阻碍 HTML 解析的,只有下载好并执行完脚本才会继续解析 HTML
defer 和 async有一个共同点:下载此类脚本都不会阻止页面呈现(异步加载),区别在于:

打开google的首页,就能看到某些样式中的图片不是一个资源地址,而是base64编码的字符串,这么做有什么好处呢? 当然是减少了一次http的请求,但也并不是什么图片都适合用base64来处理,因为图片越大,转换的base64的字符串就越长,对带宽的要求更高了。
因为二进制补零了,6位变8位,总字节长度当然就膨胀了。
为什么Base64转码后,会比原文件大?
