为了方便如今和之后前端学习和面试,在此收集和整理了Js相关的笔试面试题,供本身查阅的同时,但愿也会对你们有所帮助。javascript
前端HTML+CSS笔试题面试题
前端JS笔试题面试题
前端Vue笔试题面试题
前端小程序笔试题面试题html
Undefined、Null、Boolean、Number、String
新增:Symbol
前端
Object
是 JavaScript
中全部对象的父对象
数据封装类对象:Object、Array、Boolean、Number
和 String
其余对象:Function、Arguments、Math、Date、RegExp、Error
java
typeof undefinded //undefined
typeof null // object
typeof'abc' // string
typeof 123 // number
typeof [] // object
typeof {} // object
typeof true //boolean
typeof b // b 没有声明,可是还会显示 undefined
复制代码
===
什么时候使用==
?(考点:强制类型转换)==
比较两个值相等返回ture
===
比较二者的值和类型都相等才返回true
严格相等 0,NAN,null,undefinded,'',false
在if
语句中会强制转化为 false
node
if (obj.a == null) {
// 这里至关于 obj.a === null || obj.a ===undefinded, 简写形式
// 这里jquery 源码中推荐的写法
}
复制代码
null,undefined
的区别?一、null
: Null
类型,表明“空值”,表明一个空对象指针,使用typeof
运算获得 “object”
,因此你能够认为它是一个特殊的对象值。
二、undefined
: Undefined
类型,当一个声明了一个变量未初始化时,获得的就是undefined
。jquery
ps:一句话简单来讲null
和undefine
值比较是相等,但类型不一样。nginx
一、对象字面量的方式面试
var = {}
复制代码
二、经过构造函数方式建立。ajax
var obj = new Object();
复制代码
三、经过Object.create()
方式建立。算法
var obj = Object.create(Object.prototype);
复制代码
能够先将字符串转成一个数组,而后用数组的reverse()+join()
方法。
let str="hello word";
let b=[...str].reverse().join("");//drow olleh
复制代码
new
一个对象的过程一、建立一个新对象
二、this
指向这个对象
三、执行代码,即对this
赋值
四、隐式返回this
// 值类型
var a = 10
var b = a
a = 11
console.log(b) // 10
// 引用类型
var obj1 = {x : 100}
var obj2 = obj1
obj1.x = 200
console.log(obj2) // 200
复制代码
一、instanceof
方法 instanceof
运算符是用来测试一个对象是否在其原型链原型构造函数的属性
var arr = [];
arr instanceof Array; // true
复制代码
二、constructor
方法 constructor
属性返回对建立此对象的数组函数的引用,就是返回对象相对应的构造函数
var arr = [];
arr.constructor == Array; //true
复制代码
三、最简单的方法,这种写法兼容性最好使用Object.prototype.toString.call()
function isObjArr(value){
if (Object.prototype.toString.call(value) === "[object Array]") {
console.log('value是数组');
}else if(Object.prototype.toString.call(value)==='[object Object]'){//这个方法兼容性好一点
console.log('value是对象');
}else{
console.log('value不是数组也不是对象')
}
}
复制代码
四、ES5
新增方法isArray()
var a = new Array(123);
var b = new Date();
console.log(Array.isArray(a)); //true
console.log(Array.isArray(b)); //false
复制代码
ps:千万不能使用typeof
来判断对象和数组,由于这两种类型都会返回"object"
。
一、Set
结构去重(ES6
用法)。 ES6
提供了新的数据结构Set
。它相似于数组,可是成员的值都是惟一的,没有重复的值。
[...new Set(array)];
复制代码
二、遍历,将值添加到新数组,用indexOf()
判断值是否存在,已存在就不添加,达到去重效果。
let a = ['1','2','3',1,NaN,NaN,undefined,undefined,null,null, 'a','b','b'];
let unique= arr =>{
let newA=[];
arr.forEach(key => {
if( newA.indexOf(key)<0 ){ //遍历newA是否存在key,若是存在key会大于0就跳过push的那一步
newA.push(key);
}
});
return newA;
}
console.log(unique(a)) ;//["1", "2", "3", 1, NaN, NaN, undefined, null, "a", "b"]
// 这个方法不能分辨NaN,会出现两个NaN。是有问题的,下面那个方法好一点。
复制代码
三、利用for
嵌套for
,而后splice
去重(ES5
中最经常使用)。
function unique(arr){
for(var i=0; i<arr.length; i++){
for(var j=i+1; j<arr.length; j++){
if(arr[i]==arr[j]){ //第一个等同于第二个,splice方法删除第二个
arr.splice(j,1);
j--;
}
}
}
return arr;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", 15, false, undefined, NaN, NaN, "NaN", "a", {…}, {…}] //NaN和{}没有去重,两个null直接消失了
复制代码
四、forEach
遍历,而后利用Object.keys(对象)
返回这个对象可枚举属性组成的数组,这个数组就是去重后的数组。
let a = ['1', '2', '3', 1,NaN,NaN,undefined,undefined,null,null, 'a', 'b', 'b'];
const unique = arr => {
var obj = {}
arr.forEach(value => {
obj[value] = 0;//这步新添加一个属性,并赋值,若是不赋值的话,属性会添加不上去
})
return Object.keys(obj);//`Object.keys(对象)`返回这个对象可枚举属性组成的数组,这个数组就是去重后的数组
}
console.log(unique(a));//["1", "2", "3", "NaN", "undefined", "null", "a", "b"]
复制代码
var、let、const
之间的区别var
声明变量能够重复声明,而let
不能够重复声明 var
是不受限于块级的,而let
是受限于块级 var
会与window
相映射(会挂一个属性),而let
不与window
相映射 var
能够在声明的上面访问变量,而let
有暂存死区,在声明的上面访问变量会报错 const
声明以后必须赋值,不然会报错 const
定义不可变的量,改变了就会报错 const
和let
同样不会与window
相映射、支持块级做用域、在声明的上面访问变量会报错
This
几种不一样的使用场景一、做为构造函数执行
二、做为对象属性执行
三、做为普通函数执行
四、call apply bind
This
对象的理解一、this
老是指向函数的直接调用者(而非间接调用者)
二、若是有new
关键字,this
指向new
出来的那个对象
三、在事件中,this
指向触发这个事件的对象,特殊的是,IE
中的attachEvent
中的this
老是指向全局对象Window
ES5
做用域分为 全局做用域 和 函数做用域。 ES6
新增块级做用域,块做用域由 { }
包括,if
语句和 for
语句里面的{ }
也属于块做用域。
// 块级做用域
if (true) {
var name = 'zhangsan'
}
console.log(name)
// 函数和全局做用域
var a = 100
function fn () {
var a = 200
console.log('fn', a)
}
复制代码
JS
建立10个<a>
标签,点击的时候弹出来对应的序号?(考点:做用域)var i
for (i = 0; i < 10; i++) {
(function (i) {
var a = document.createElement('a')
a.innerHTML = i + '<br>'
a.addEventListener('click', function (e) {
e.preventDefault()
alert(i)
})
document.body.appendChild(a)
})(i)
}
复制代码
一、做用域链的做用是保证执行环境里有权访问的变量和函数是有序的,做用域链的变量只能向上访问,变量访问到window
对象即被终止,做用域链向下访问变量是不被容许的
二、简单的说,做用域就是变量与函数的可访问范围,即做用域控制着变量与函数的可见性和生命周期
三、通俗来讲,通常状况下,变量取值到 建立 这个变量 的函数的做用域中取值。 可是若是在当前做用域中没有查到值,就会向上级做用域去查,直到查到全局做用域,这么一个查找过程造成的链条就叫作做用域链
var a = 100
function fn () {
var b = 200
// 当前做用域没有定于的变量,即‘自由变量’
console.log(a)
console.log(b)
}
fn()
console.log(a) 去父级做用域找a自由变量 做用域链
复制代码
闭包就是可以读取其余函数内部变量的函数
闭包是指有权访问另外一个函数做用域中变量的函数,建立闭包的最多见的方式就是在一个函数内建立另外一个函数,经过另外一个函数访问这个函数的局部变量,利用闭包能够突破做用链域
function F1 () {
var a = 100
// 返回一个函数,函数做为返回值
return function () {
console.log(a)
}
}
// f1 获得一个函数
var f1 = F1()
var a = 200
f1() // 100 定义的时候父级做用域
复制代码
函数内再嵌套函数
内部函数能够引用外层的参数和变量
参数和变量不会被垃圾回收机制回收
使用闭包主要是为了设计私有的方法和变量。闭包的优势是能够避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易形成内存泄露。在js中,函数即闭包,只有函数才会产生做用域的概念
闭包的最大用处有两个,一个是能够读取函数内部的变量,另外一个就是让这些变量始终保持在内存中
闭包的另外一个用处,是封装对象的私有属性和私有方法
好处:可以实现封装和缓存等;
坏处:就是消耗内存、不正当使用会形成内存溢出的问题
因为闭包会使得函数中的变量都被保存在内存中,内存消耗很大,因此不能滥用闭包,不然会形成网页的性能问题,在IE中可能致使内存泄露 解决方法是,在退出函数以前,将不使用的局部变量所有删除
闭包的两个场景:函数做为返回值 和 函数做为参数传递
function F1 () {
var a = 100
// 返回一个函数,函数做为返回值
return function () {
console.log(a)
}
}
// f1 获得一个函数
var f1 = F1()
var a = 200
f1() // 100 定义的时候父级做用域
function F2 (fn) {
var a = 200
fn()
}
F2(f1)
复制代码
// 闭包实际应用中主要用于封装变量 收敛权限
function isFirstLoad() {
var _list = []
return function (id) {
if (_list.indexOf(id) >= 0) {
return false
} else {
_list.push(id)
return true
}
}
}
// 使用
var firstLoad = new isFirstLoad()
firstLoad(10) //true
firstLoad(10) //false
firstLoad(30) //true
复制代码
每一个对象都会在其内部初始化一个属性,就是prototype
(原型), 当咱们访问一个对象的属性时,若是这个对象内部不存在这个属性,那么他就会去prototype
里找这个属性,这个prototype
又会有本身的prototype
,因而就这样一直找下去,也就是咱们平时所说的原型链的概念
原型和原型链关系
关系:instance.constructor.prototype = instance.__proto__
原型和原型链特色
JavaScript
对象是经过引用来传递的,咱们建立的每一个新对象实体中并无一份属于本身的原型副本。当咱们修改原型时,与之相关的对象也会继承这一改变 当咱们须要一个属性的时,Javascript
引擎会先看当前对象中是否有这个属性, 若是没有的 就会查找他的Prototype对象是否有这个属性,如此递推下去,一直检索到 Object
内建对象
PS: 1.全部的引用类型(数组,对象,函数)都具备对象的特性,便可自由扩展属性(除了‘null
’)除外
2.全部的引用类型(数组,对象,函数)都有一个_proto_
(隐式原型)属性,属性值是一个普通对象
3.全部的函数,都有一个prototype
(显示原型)的属性,也是一个普通对象
4.全部的引用类型(数组,对象,函数)_proto_
属性值指向他的构造的‘prototype
’ 属性值
_proto_
(即它的构造函数的prototype
) 中寻找// 构造函数
function Foo(name, age){
this.name = name
}
Foo.prototype.alertName = function () {
alert(this.name)
}
//建立实例
var f = new Foo('zhangsan')
f.printName = function () {
console.log(this.name)
}
//测试
f.printName()
f.alertName()
复制代码
var item
for (item in f) {
// 高级浏览器已经在 for in 中屏蔽了来自原型的属性
// 可是这里建议你们仍是加上这个判断,保证程序的健壮性
if (f.hasOwnProperty(item)) {
console.log(item)
}
}
复制代码
f.toString() //到f._proto_._proto_ 中去找
复制代码
同步交互
:指发送一个请求,须要等待返回,而后才可以发送下一个请求,有个等待过程。 异步交互
:指发送一个请求,不须要等待返回,随时能够再发送下一个请求,即不须要等待。 相同的地方
:都属于交互方式,都是发送请求。 不一样的地方
:一个须要等待,一个不须要等待。
简单而言,同步就是必须一件一件的作事,等前一件事作完后才能作下一件事。而异步这是把事情指派给别人后,接着继续作下一件事,没必要等别人返回的结果。
举例:
一、广播,就是一个异步例子。发起者不关心接收者的状态。不须要等待接收者的返回信息; 在部分状况下,咱们的项目开发中都会优先选择不须要等待的异步交互方式。
二、电话,就是一个同步例子。发起者须要等待接收者,接通电话后,通讯才开始。须要等待接收者的返回信息 好比银行的转帐系统,对数据库的保存操做等等,都会使用同步交互操做。
ps: alert
是同步,setTimeout
和setInterval
是异步,同步会阻塞代码执行,而异步不会
一、回调函数
优势:简单、容易理解
缺点:不利于维护,代码耦合高
二、事件监听(采用时间驱动模式,取决于某个事件是否发生):
优势:容易理解,能够绑定多个事件,每一个事件能够指定多个回调函数
缺点:事件驱动型,流程不够清晰
三、发布/订阅(观察者模式)
相似于事件监听,可是能够经过‘消息中心’,了解如今有多少发布者,多少订阅者
四、Promise对象
优势:能够利用then
方法,进行链式写法;能够书写错误时的回调函数;
缺点:编写和理解,相对比较难
五、Generator函数
优势:函数体内外的数据交换、错误处理机制
缺点:流程管理不方便
六、async函数
优势:内置执行器、更好的语义、更广的适用性、返回的是Promise
、结构清晰。
缺点:错误处理机制
简单来讲:由于js
是单线程的,浏览器遇到setTimeout
或者setInterval
会先执行完当前的代码块,在此以前会把定时器推入浏览器的待执行事件队列里面,等到浏览器执行完当前代码以后会看一下事件队列里面有没有任务,有的话才执行定时器的代码。 因此即便把定时器的时间设置为0
仍是会先执行当前的一些代码。
setTimeout
的笔试题console.log(1)
setTimeout(function () {
console.log(2)
},0)
console.log(3)
setTimeout(function () {
console.log(4)
},1000)
console.log(5)
//结果为 1 3 5 2 4
复制代码
一、定时任务:setTimeout,setInverval
二、网络请求:ajax
请求,动态<img>
加载
三、事件绑定
API
一、forEach
方法,是最基本的方法,就是遍历与循环,默认有3个传参:分别是遍历的数组内容item
、数组索引index
、和当前遍历数组Array
二、map
方法,基本用法与forEach
一致,可是不一样的,它会返回一个新的数组,因此在callback
须要有return
值,若是没有,会返回undefined
一般咱们会用循环的方式来遍历数组。可是循环是 致使js 性能问题的缘由之一。通常咱们会采用下几种方式来进行数组的遍历 for in循环
for循环
forEach
一、这里的 forEach
回调中两个参数分别为 value,index
二、forEach
没法遍历对象
三、IE
不支持该方法;Firefox
和 chrome
支持
四、forEach
没法使用 break,continue
跳出循环,且使用 return
是跳过本次循环
五、能够添加第二个参数,为一个数组,回调中的this会指向这个数组,若没有添加,则是指向window
;
在方式一中,for-in
须要分析出array
的每一个属性,这个操做性能开销很大。用在 key
已知的数组上是很是不划算的。因此尽可能不要用for-in
,除非你不清楚要处理哪些属性,例如JSON
对象这样的状况
在方式2中,循环每进行一次,就要检查一下数组长度。读取属性(数组长度)要比读局部变量慢,尤为是当array
里存放的都是 DOM
元素,由于每次读取都会扫描一遍页面上的选择器相关元素,速度会大大下降
forEach
函数function forEach(obj, fn) {
var key
// 判断类型
if (obj instanceof Array) {
obj.forEach(function (item, index) {
fn(index, item)
})
} else {
for (key in obj) {
fn ( key, obj[key])
}
}
}
复制代码
API
map: 遍历数组,返回回调返回值组成的新数组
forEach: 没法break,能够用try/catch中throw new Error来中止
filter: 过滤
some: 有一项返回true,则总体为true
every: 有一项返回false,则总体为false
join: 经过指定链接符生成字符串
push / pop: 末尾推入和弹出,改变原数组, 返回推入/弹出项【有误】
unshift / shift: 头部推入和弹出,改变原数组,返回操做项【有误】
sort(fn) / reverse: 排序与反转,改变原数组
concat: 链接数组,不影响原数组, 浅拷贝
slice(start, end): 返回截断后的新数组,不改变原数组
splice(start, number, value...): 返回删除元素组成的数组,value 为插入项,改变原数组
indexOf / lastIndexOf(value, fromIndex): 查找数组项,返回对应的下标
reduce / reduceRight(fn(prev, cur), defaultPrev): 两两执行,prev 为上次化简函数的return值,cur 为当前值(从第二项开始)
复制代码
API
var obj = {
x: 100,
y: 200,
z: 300
}
var key
for (key in obj) {
// 注意这里的 hasOwnProperty,再讲原型链的时候讲过
if (obj.hasOwnProperty(key)) {
console.log(key, obj[key])
}
}
复制代码
2020-06-10
格式的日期Date.now() // 获取当前时间毫秒数
var dt = new Date()
dt.getTime() //获取毫秒数
dt.getFullYear() // 年
dt.getMonth() // 月 (0-11)
dt.getDate() // 日 (0-31)
dt.getHours() // 小时 (0-23)
dt.getMinutes() //分钟 (0-59)
dt.getSeconds() //秒 (0-59)
复制代码
ps: ES6
新增padStart(),padEnd()
方法可用来返回06
格式日期
var random = Math.random()
var random = random + '0000000000'
console.log(random)
var random = random.slice(0, 10)
console.log(random)
复制代码
DOM
和BOM
操做DOM
是哪一种基本的数据结构DOM
是一种树形结构的数据结构
DOM
操做的经常使用API
有哪些一、获取DOM
节点,以及节点的property
和Attribute
二、获取父节点,获取子节点
三、新增节点,删除节点
DOM
节点的Attribute
和property
有何区别property
只是一个JS
对象的属性修改和获取 Attribute
是对html
标签属性的修改和获取
DOM
的节点操做建立新节点
createDocumentFragment() //建立一个DOM片断
createElement() //建立一个具体的元素
createTextNode() //建立一个文本节点
复制代码
添加、移除、替换、插入
appendChild() //添加
removeChild() //移除
replaceChild() //替换
insertBefore() //插入
复制代码
查找
getElementsByTagName() //经过标签名称
getElementsByName() //经过元素的Name属性的值
getElementById() //经过元素Id,惟一性
复制代码
如何检测浏览器的类型
能够经过检测navigator.userAgent
在经过不通浏览器的不通来检测
var ua = navigator.userAgent
var isChrome = ua.indexOf('Chrome')
console.log(isChrome)
复制代码
拆解url
的各部分
使用location
里面的location.href location.protocol location.pathname location.search location.hash
来获取各类参数
console.log(location.href)
console.log(location.host) //域名
console.log(location.protocol)
console.log(location.pathname) //路径
console.log(location.search) // 参数
console.log(location.hash)
// history
history.back()
history.forward()
复制代码
事件代理(Event Delegation
),又称之为事件委托。是 JavaScript
中经常使用绑定事件的经常使用技巧。顾名思义,“事件代理”便是把本来须要绑定的事件委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM
元素的事件冒泡。
使用事件代理的好处是:
一、能够提升性能
二、能够大量节省内存占用,减小事件注册,好比在table
上代理全部td
的click
事件就很是棒
三、能够实现当新增子对象时无需再次对其绑定
W3C
中定义事件的发生经历三个阶段:捕获阶段(capturing)、目标阶段(targetin)、冒泡阶段(bubbling)
冒泡型事件:
当你使用事件冒泡时,子级元素先触发,父级元素后触发 捕获型事件:
当你使用事件捕获时,父级元素先触发,子级元素后触发 DOM事件流:
<时支持两种事件模型:捕获型事件和冒泡型事件 阻止冒泡:
在W3c
中,使用stopPropagation()
方法;在IE
下设置cancelBubble = true
阻止捕获:
阻止事件的默认行为,例如click - <a>后
的跳转。在W3c
中,使用preventDefault()
方法,在IE
下设置window.event.returnValue = false
function bindEvent(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)
}
}else{
fn(e)
}
})
}
复制代码
当给某元素绑定一个事件的时候,首先会触发本身绑定的,而后会逐层向上级查找事件,这就是事件冒泡
var p1 = document.getElementById('p1')
var body = document.body
function bindEvent(elem, type, fn) {
elem.addEventListener(type, fn)
}
bindEvent(p1, 'click', function (e) {
e.stopPropagation()
var target = e.target
alert("激活")
})
bindEvent(body, 'click', function (e) {
var target = e.target
alert("取消")
})
复制代码
可使用代理,经过对父级元素绑定一个事件,经过判断事件的target
属性来进行判断,添加行为
var div1 = document.getElementById('div1')
var div2 = document.getElementById('div2')
function bindEvent(elem, type, fn) {
elem.addEventListener(type, fn)
}
bindEvent(div1, 'click', function (e) {
var target = e.target
alert(target.innerHTML)
})
bindEvent(div2, 'click', function (e) {
var target = e.target
alert(target.innerHTML)
})
复制代码
Ajax
原理Ajax
的原理简单来讲是在用户和服务器之间加了—个中间层(AJAX
引擎),经过XmlHttpRequest
对象来向服务器发异步请求,从服务器得到数据,而后用javascript
来操做DOM
而更新页面。使用户操做与服务器响应异步化。这其中最关键的一步就是从服务器得到请求数据 Ajax
的过程只涉及JavaScript、XMLHttpRequest和DOM
。XMLHttpRequest
是ajax的核心机制
ajax
,不依赖第三方库// 1. 建立链接
var xhr = null;
xhr = new XMLHttpRequest()
// 2. 链接服务器
xhr.open('get', url, true)
// 3. 发送请求
xhr.send(null);
// 4. 接受请求
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
success(xhr.responseText);
} else { // fail
fail && fail(xhr.status);
}
}
}
复制代码
ajax
的优势和缺点
ajax的优势
一、无刷新更新数据(在不刷新整个页面的状况下维持与服务器通讯)
二、异步与服务器通讯(使用异步的方式与服务器通讯,不打断用户的操做)
三、前端和后端负载均衡(将一些后端的工做交给前端,减小服务器与宽度的负担)
四、界面和应用相分离(ajax
将界面和应用分离也就是数据与呈现相分离)
ajax的缺点
一、ajax不支持浏览器back按钮
二、安全问题 Aajax
暴露了与服务器交互的细节
三、对搜索引擎的支持比较弱
四、破坏了Back
与History
后退按钮的正常行为等浏览器机制。
跨域问题是这是浏览器为了安全实施的同源策略致使的,同源策略限制了来自不一样源的document、脚本
,同源的意思就是两个URL
的域名、协议、端口要彻底相同。 script
标签jsonp
跨域、nginx
反向代理、node.js
中间件代理跨域、后端在头部信息设置安全域名、后端在服务器上设置cors
。
ps:有三个标签容许跨域加载资源: <img src=xxx> <link href = xxx> <script src=xxx>
三个标签场景: <img>
用于打点统计,统计网站多是其余域 <link> <script>
可使用CDN
,CDN
的也是其余域 <script>
能够用于JSONP
⚠️跨域注意事项
全部的跨域请求都必须通过信息提供方容许
若是未经容许便可获取,那么浏览器同源策略出现漏洞
XML
和JSON
的区别?数据体积方面 JSON
相对于XML
来说,数据的体积小,传递的速度更快些。
数据交互方面 JSON
与JavaScript
的交互更加方便,更容易解析处理,更好的数据交互
数据描述方面 JSON
对数据的描述性比XML
较差
传输速度方面 JSON
的速度要远远快于XML
get
和post
的区别一、get
和post
在HTTP
中都表明着请求数据,其中get请求相对来讲更简单、快速,效率高些
二、get
相对post
安全性低
三、get
有缓存,post
没有
四、get
体积小,post
能够无限大
五、get
的url
参数可见,post
不可见
六、get
只接受ASCII
字符的参数数据类型,post
没有限制
七、get
请求参数会保留历史记录,post
中参数不会保留
八、get
会被浏览器主动catch,post
不会,须要手动设置
九、get
在浏览器回退时无害,post
会再次提交请求
何时使用post
?
post
通常用于修改服务器上的资源,对所发送的信息没有限制。好比
一、没法使用缓存文件(更新服务器上的文件或数据库)
二、向服务器发送大量数据(POST
没有数据量限制)
三、发送包含未知字符的用户输入时,POST
比 GET
更稳定也更可靠
TCP
创建链接为何须要三次?TCP
协议的通讯双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 三次握手的过程便是通讯双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤ES5
的继承和ES6
的继承有什么区别?ES5
的继承时经过prototype
或构造函数机制来实现。ES5
的继承实质上是先建立子类的实例对象,而后再将父类的方法添加到this
上(Parent.apply(this)
)。
ES6
的继承机制彻底不一样,实质上是先建立父类的实例对象this
(因此必须先调用父类的super()
方法),而后再用子类的构造函数修改this
。
具体的:ES6
经过class
关键字定义类,里面有构造方法,类之间经过extends
关键字实现继承。子类必须在constructor
方法中调用super
方法,不然新建实例报错。由于子类没有本身的this
对象,而是继承了父类的this
对象,而后对其进行加工。若是不调用super
方法,子类得不到this
对象。
ps:super
关键字指代父类的实例,即父类的this
对象。在子类构造函数中,调用super
后,才可以使用this
关键字,不然报错
javascript
如何实现继承?一、构造继承
二、原型继承
三、实例继承
四、拷贝继承
原型prototype
机制或apply和call
方法去实现较简单,建议使用构造函数与原型混合方式
function Parent(){
this.name = 'wang';
}
function Child(){
this.age = 28;
}
Child.prototype = new Parent();//继承了Parent,经过原型
var demo = new Child();
alert(demo.age);
alert(demo.name);//获得被继承的属性
}
复制代码
ES6
的理解新增模板字符串(为JavaScript
提供了简单的字符串插值功能)
箭头函数 for-of
(用来遍历数据—例如数组中的值。) arguments
对象可被不定参数和默认参数完美代替。 ES6
将promise
对象归入规范,提供了原生的Promise
对象。
增长了let和const
命令,用来声明变量。
增长了块级做用域。 let
命令实际上就增长了块级做用域。
还有就是引入module
模块的概念
this
对象,就是定义时所在的对象,而不是使用时所在的对象new
命令,不然会抛出一个错误arguments
对象,该对象在函数体内不存在。若是要用,能够用Rest
参数代替yield
命令,所以箭头函数不能用做Generator
函数forEach、for in、for of
三者区别forEach
更多的用来遍历数 for in
通常经常使用来遍历对象或json
for of
数组对象均可以遍历,遍历对象须要经过和Object.keys()
for in
循环出的是key,for of
循环出的是value
Set、Map
的区别应用场景Set
用于数据重组,Map用于数据储存
Set:
1,成员不能重复
2,只有键值没有键名,相似数组
3,能够遍历,方法有add, delete,has
Map:
1,本质上是健值对的集合,相似集合
2,能够遍历,能够跟各类数据格式转换
promise
对象的用法,手写一个promise
promise
是一个构造函数,下面是一个简单实例
var promise = new Promise((resolve,reject) => {
if (操做成功) {
resolve(value)
} else {
reject(error)
}
})
promise.then(function (value) {
// success
},function (value) {
// failure
})
复制代码
Promise
的使用场景,'Promise
'它所解决的问题以及如今对于异步操做的解决方案。Promise
的使用场景:ajax
请求,回调函数,复杂操做判断。 Promise
是ES6
为了解决异步编程所诞生的。
异步操做解决方案:Promise、Generator
、定时器(不知道算不算)、还有ES7
的async
ECMAScript6
怎么写class
,为何会出现class
这种东西?这个语法糖可让有OOP
基础的人更快上手js
,至少是一个官方的实现了 但对熟悉js
的人来讲,这个东西没啥大影响;一个Object.creat()
搞定继承,比class
简洁清晰的多
每次比较相邻的两个数,若是后一个比前一个小,换位置
var arr = [3, 1, 4, 6, 5, 7, 2];
function bubbleSort(arr) {
for (var i = 0; i < arr.length - 1; i++) {
for(var j = 0; j < arr.length - i - 1; j++) {
if(arr[j + 1] < arr[j]) {
var temp;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
console.log(bubbleSort(arr));
复制代码
采用二分法,取出中间数,数组每次和中间数比较,小的放到左边,大的放到右边
var arr = [3, 1, 4, 6, 5, 7, 2];
function quickSort(arr) {
if(arr.length == 0) {
return []; // 返回空数组
}
var cIndex = Math.floor(arr.length / 2);
var c = arr.splice(cIndex, 1);
var l = [];
var r = [];
for (var i = 0; i < arr.length; i++) {
if(arr[i] < c) {
l.push(arr[i]);
} else {
r.push(arr[i]);
}
}
return quickSort(l).concat(c, quickSort(r));
}
console.log(quickSort(arr));
复制代码
<img id="img1" src="preview.png" data-realsrc = "abc.png"/>
<script type = "text/javascript">
var img1 = document.getElementById("img1")
img1.src = img1.getAttribute('data-realsrc')
</script>
复制代码
DOM
查询// 未缓存 DOM查询
var i
for (i = 0; i < document.getElementByTagName('p').length; i++) {
//todo
}
//缓存了DOM查询
var pList = document.getElementByTagName('p')
var i
for (i= 0; i < pList.length; i++) {
// todo
}
复制代码
DOM
插入var listNode = document.getElementById('list')
//要插入10个li标签
var frag = document.createDocumentFragment();
var x,li
for (x = 0; x < 10; x++) {
li = document.createElement('li')
li.innerHTML = "List item" + x
frag.appendChild(li)
}
listNode.appendChild(frag)
复制代码
var textarea = document.getElementById('text')
var timeoutId
textarea.addEventListener('keyup', function () {
if (timeoutId) {
clearTimeout(timeoutId)
}
timeoutId = setTimeout(function () {
//触发事件
},100)
})
复制代码
window.addEventListener('load', function () {
//页面的所有资源加载完才会去执行,包括图片,视频
})
document.addEventListener('DOMContentLoaded', function() {
//DOM 渲染完便可执行,此时图片,视频还可能没有加载完成
})
复制代码
首先能够经过 Object.assign
来解决这个问题
let a = {
age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1
复制代码
这个问题一般能够经过JSON.parse(JSON.stringify(object))
来解决
let a = {
age: 1,
jobs: {
first: 'FE'
}
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'native'
console.log(b.jobs.first) // FE
复制代码
[1, [2], 3].flatMap(v => v)
// -> [1, 2, 3]
复制代码
若是想将一个多维数组完全的降维,能够这样实现
const flattenDeep = (arr) => Array.isArray(arr)
? arr.reduce( (a, b) => [...a, ...flattenDeep(b)] , [])
: [arr]
flattenDeep([1, [[2], [3, [4]], 5]])
复制代码
在开发中,可能会遇到这样的状况。有些资源不须要立刻用到,可是但愿尽早获取,这时候就可使用预加载 预加载实际上是声明式的 fetch
,强制浏览器请求资源,而且不会阻塞 onload
事件,可使用如下代码开启预加载
<link rel="preload" href="http://example.com">
复制代码
预加载能够必定程度上下降首屏的加载时间,由于能够将一些不影响首屏但重要的文件延后加载,惟一缺点就是兼容性很差
能够经过预渲染将下载的文件预先在后台渲染,可使用如下代码开启预渲染
<link rel="prerender" href="http://poetries.com">
复制代码
一、尽量把 <script> 标签放在 body 以后,避免 JS 的执行卡住 DOM 的渲染,最大程度保证页面尽快地展现出来
二、尽量合并 JS 代码:提取公共方法,进行面向对象设计等……
三、CSS 能作的事情,尽可能不用 JS 来作,毕竟 JS 的解析执行比较粗暴,而 CSS 效率更高。
四、尽量逐条操做 DOM,并预约好 CSs 样式,从而减小 reflow 或者 repaint 的次数。
五、尽量少地建立 DOM,而是在 HTML 和 CSS 中使用 display: none 来隐藏,按需显示。
六、压缩文件大小,减小资源下载负担。
复制代码
一、不要在同一行声明多个变量
二、请使用===/!==来比较true/false或者数值
三、使用对象字面量替代new Array这种形式
四、不要使用全局变量
五、Switch语句必须带有default分支
六、函数不该该有时候有返回值,有时候没有返回值
七、For循环必须使用大括号
八、IF语句必须使用大括号
九、for-in循环中的变量 应该使用var关键字明确限定做用域,从而避免做用域污染
复制代码