前端面试题总结

Ajax
readyState表示xhr对象的请求状态,取值范围是0——4,分别表示5个不同的状态。
0:(未初始化)xhr对象已经创建,但还没有调用open()方法。值为0表示对象已经存在,否则浏览器会报错:对象不存在。
1 :(载入/发送请求)调用open()方法对xhr对象进行初始化,根据参数(method,url,true),完成对象状态的设置。并调用send()方法开始向服务端发送请求。值为1表示正在向服务端发送请求。
2 :(载入完成/响应接收)接收服务器端响应回的数据。但获得的还只是服务端响应的原始数据,并不能直接在客户端使用。值为2表示send()请求方法执行完成,并已经接收完全部的响应数据(未解析)。
3 - (交互/解析数据)正在解析从服务器端接收到的响应数据。即根据服务器端响应头部返回的MIME类型把数据转换成能通过responseBody、responseText或responseXML属性存取的格式,为在客户端调用作好准备。值为3表示正在解析加载数据。
4 - (后台处理完成)响应内容解析完成,可以在客户端调用了。此阶段确认全部数据都已经解析为客户端可用的格式,解析已经完成。值为4表示数据解析完毕,可以通过XMLHttpRequest对象的相应属性取得数据。

总之,整个XMLHttpRequest对象的生命周期应该包含如下阶段:
创建-0初始化请求-1发送请求-2接收数据-3解析数据-4完成 。

Ajax原理

Ajax 的原理简单来说是在⽤户和服务器之间加了—个中间层( AJAX 引擎),通过XmlHttpRequest 对象来向服务器发异步请求,从服务器获得数据,然后⽤ javascript来操作 DOM ⽽更新⻚⾯。使⽤户操作与服务器响应异步化。这其中最关键的⼀步就是从服务器获得请求数据
Ajax 的过程只涉及 JavaScript 、 XMLHttpRequest 和 DOM 。 XMLHttpRequest 是ajax的核⼼机制

/** 1. 创建连接 **/
var xhr = null;
xhr = XMLHTTPRequest ? new XMLHttpRequest() : new window.ActiveXObject('Microsoft.XMLHTTP');
/** 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 {
            /** false **/
            fail && fail(xhr.status);
        }
    }
}

ajax 有那些优缺点?
优点:
通过异步模式,提升了⽤户体验.
优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占⽤.
Ajax 在客户端运⾏,承担了⼀部分本来由服务器承担的⼯作,减少了⼤⽤户量下的服务器负载。
Ajax 可以实现动态不刷新(局部刷新)
缺点:
安全问题 AJAX 暴露了与服务器交互的细节。
对搜索引擎的⽀持⽐较弱。
不容易调试。

typeOf(null)//Object

表示一个空对象引用。
alert(null instanceof Object); 返回值为false,( null表示为空的引用;instanceof 表示某个变量是否是某个对象的实例)

HTTP的GET和POST有什么区别?

HTTP状态码200、302、401、404、500分别代表什么意思?

10一个页面上有大量的图片(大型电商网站),加载很慢,你有哪些图片优化这些图片的加载,给用户更好

图⽚懒加载,在⻚⾯上的未可视区域可以添加⼀个滚动事件,判断图⽚位置与浏览器顶端的距离与⻚⾯的距离,如果前者⼩于后者,优先加载。
如果为幻灯⽚、相册等,可以使⽤图⽚预加载技术,将当前展示图⽚的前⼀张和后⼀张优先下载。
如果图⽚为css图⽚,可以使⽤ CSSsprite , SVGsprite , Iconfont 、 Base64 等技术。
如果图⽚过⼤,可以使⽤特殊编码的图⽚,加载时会先加载⼀张压缩的特别厉害的缩略图,以提⾼⽤户体验。
如果图⽚展示区域⼩于图⽚的真实⼤⼩,则因在服务器端根据业务需要先⾏进⾏图⽚压缩,图⽚压缩后⼤⼩与展示⼀致。

base64的原理及优缺点

优点:可以加密,减少了 HTTP 请求
缺点:是需要消耗 CPU 进⾏编解码

说一说前端性能优化有哪些方法

Vue有哪些生命周期函数?

undefined + 1 === NaN,undefined将它强制转换成数值会返回NaN

17完成function a()代码,实现点击“这是第N条”列表项的时候alert n (n >= 0 && n <= 2)


//闭包实现
var lis=document.querySelectorAll('li');
for (var i = 0; i < lis.length; i++) {
    var li = lis[i];
    li.onclick=(function(index){
        return function(e){
        	alert(index);
        };
    })(i);
}

21有哪些方法可以解决跨域?三种以上(考虑到兼容性的话用哪种)

vue和react内部是怎么实现数据的双向绑定的?react钩子的状态的实现???

vue.js 则是采⽤数据劫持结合发布者-订阅者模式的⽅式,通过Object.defineProperty() 来劫持各个属性的 setter , getter ,在数据变动时发布消息给订阅者,触发相应的监听回调

vue objectDefined proxy v-model

React并没有自带的双向绑定,需要自己实现,结合setState()以及onChange事件来实现,每次文本框改变文本(即触发onChange事件),就使用setState()改变state数据

import React, { Component } from "react"
import ReactDOM from "react-dom"
 
export default class DataBind extends Component{
    constructor(props){
        super(props)
        this.state = {
            value: "Name"
        }
    }
    handleChange(e){
        this.setState({
            value : e.target.value
        })
    }
    
    render(){
        return(
        

{this.state.value}

) } }

99Vue 和 React 之间的区别

Vue 的表单可以使⽤ v-model ⽀持双向绑定,相⽐于 React 来说开发上更加⽅便,当然了 v-model 其实就是个语法糖,本质上和 React 写表单的⽅式没什么区别

改变数据⽅式不同, Vue 修改状态相⽐来说要简单许多, React 需要使⽤ setState来改变状态,并且使⽤这个 API 也有⼀些坑点。并且 Vue 的底层使⽤了依赖追踪,⻚⾯更新渲染已经是最优的了,但是 React 还是需要⽤户⼿动去优化这⽅⾯的问题。

React 16 以后,有些钩⼦函数会执⾏多次,这是因为引⼊ Fiber 的原因。React 需要使⽤ JSX ,有⼀定的上⼿成本,并且需要⼀整套的⼯具链⽀持,但是完全可以通过 JS 来控制⻚⾯,更加的灵活。 Vue 使⽤了模板语法,相⽐于 JSX 来说没有那么灵活,但是完全可以脱离⼯具链,通过直接编写 render 函数就能在浏览器中运⾏。

在⽣态上来说,两者其实没多⼤的差距,当然 React 的⽤户是远远⾼于 Vue 的

102发布-订阅模式

通过⼀对⼀或者⼀对多的依赖关系,当对象发⽣改变时,订阅⽅都会收到通知。在现实⽣活中,也有很多类似场景,⽐如我需要在购物⽹站上购买⼀个产品,但是发现该产品⽬前处于缺货状态,这时候我可以点击有货通知的按钮,让⽹站在产品有货的时候通过短信通知我。在实际代码中其实发布-订阅模式也很常⻅,⽐如我们点击⼀个按钮触发了点击事件就是使⽤了该模式

vue数据双向绑定也用到了发布订阅模式

观察者模式和发布订阅模式最大的区别就是发布订阅模式有个**事件调度中心 **

观察者模式中观察者和目标直接进行交互,而发布订阅模式中统一由调度中心进行处理,订阅者和发布者互不干扰。这样一方面实现了解耦,还有就是可以实现更细粒度的一些控制。比如发布者发布了很多消息,但是不想所有的订阅者都接收到,就可以在调度中心做一些处理,类似于权限控制之类的。还可以做一些节流操作。

函数的哪些原生方法可以改变其执行的上下文 call apply bind

25 ES6新增了哪些特性至少五个

1.新增了块级作用域(let,const)

2.提供了定义类的语法糖(class)

3.新增了一种基本数据类型(Symbol)

4.新增了变量的解构赋值

5.函数参数允许设置默认值,新增了箭头函数。

6.数组新增了一些API,如isArray / from / of 方法;数组实例新增了 entries(),keys() 和 values() 等方法。

7.对象和数组新增了扩展运算符

8.ES6新增了模块化(import / export)

9.ES6新增了Set和Map数据结构。

10.ES6原生提供Proxy构造函数,用来生成Proxy实例

11.ES6新增了生成器(Generator)和遍历器(Iterator)

26浅拷贝

// 1. ...实现
let copy1 = {...{x:1}}

// 2. Object.assign实现

let copy2 = Object.assign({}, {x:1})

深拷贝(遍历一个对象用for in)

deepClone = (initalObj) => {
    const obj = {};
    if(typeof initalObj !== 'object'){
    	return initalObj
    }
    for (const key in initalObj) {
        if (typeof initalObj[key] === 'object') {
            //对数组特殊处理
            if (Array.isArray(initalObj[key])) {
                //用map方法返回新数组,将数组中的元素递归
                obj[key] = initalObj[key].map(item => deepClone(item))
            } else {
            //递归返回新的对象
            	obj[key] = deepClone(initalObj[key]);
            }
        } else if (typeof initalObj[key] === 'function') {
            //返回新函数
            obj[key] = initalObj[key].bind(obj);
        } else {
            //基本类型直接返回
            obj[key] = initalObj[key];
        }
    }
    return obj;
}
//
JSON.parse(JSON.stringify(obj))

111扁平化数组

//ES6
var arr = [1, [2, [3]], 4, [5]];
arr.flat(Infinity);
//ES5第一种
function flatArr (arr) {	
    var resultArr = [];	
    arr.forEach(function (item) { 
        //数组遍历最好用forEach		
        var str = Object.prototype.toString.call(item);		
        if (str.indexOf("Array") !== -1) {			
        	resultArr = resultArr.concat(flatArr(item));		
        }else {			
        	resultArr = resultArr.concat(item);		
        }	
    });	
    return resultArr;
}
//迭代
//对于把递归转换成迭代,很多情况下都需要一个stack来模拟函数调用。先看代码:
function flatten2(arr) {
  const stack = [...arr];
  const res = [];
  while (stack.length) {
    // 从栈里取出
    const next = stack.pop();
    if (Array.isArray(next)) {
      // 把next扁平化,然后放入stack中
      stack.push(...next);
    } else {
      res.push(next);
    }
  }
  // reverse to restore input order
  return res.reverse();
}
console.log(flatten2(arr))
递归是重复调用函数自身实现循环。迭代是函数内某段代码实现循环,循环代码中参与运算的变量同时是保存结果的变量,当前保存的结果作为下一次循环计算的初始值。
递归循环中,遇到满足终止条件的情况时逐层返回来结束。迭代则使用计数器结束循环。当然很多情况都是多种循环混合采用,这要根据具体需求。
结构不同:递归与迭代都是基于控制结构:迭代用重复结构,而递归用选择结构。
//第二种
var tempArr = arr.toString().split(","); 
//arr.toString()的结果是"1, 2, 3, 4, 5",
//arr.toString().split(",")结果为["1", "2", "3", "4", "5"]
var resultArr = tempArr.map(function (item) {	
	return parseInt(item);
});
console.log(resultArr);
//第三种
var tempArr = arr.join().split(",");
var resultArr = tempArr.map(function (item) {	
	return parseInt(item);
});
console.log(resultArr);

27请基于vue框架,实现一个父组件调用子组件方法的示例

方案一:通过ref直接调用子组件的方法;

//父组件中
    


//子组件中


方案二:通过组件的 e m i t 、 emit、 emiton方法;

//父组件中    //子组件中

至于项目中的$emit,是父子组件间传值

js实现二维数组去重

const removeRepeat1 = (arr) => {
  const obj={};
  return arr.filter(item=>{
    if(!obj[item.toString()]) {
      obj[item.toString()]=item.toString();
      return true;
    }
  });
}
数组去重⽅法总结
⽅法⼀、利⽤ES6 Set去重(ES6中最常⽤)
function unique (arr) {
	return Array.from(new Set(arr))
}
或者[...new Set(arr)]
⽅法⼆、利⽤for嵌套for,然后splice去重(ES5中最常⽤)
function unique(arr){ 
    for(var i=0; i

32使用setTimeout模拟实现一个setInterval的功能

setInterval = () =>{	    console.log(1)     //使用递归	    setTimeout(setInterval,1000);};setInterval()

34请写出React16的新特性,至少五个

render方法新增返回类型

render方法支持直接返回string,number,boolean,null,portal,以及fragments(带有key属性的数组),这可以在一定程度上减少页面的DOM层级

新的组件生命周期钩子

static getDerivedStateFromProps(nextProps, prevState)

componentDidCatch(error, info)

如果错误在组件的渲染或者生命周期方法中被抛出,则会触发该函数。

性能方面

lazy / Suspense

React.lazy() 提供了动态 import 组件的能力,实现代码分割。

Suspense 作用是在等待组件时 suspend(暂停)渲染,并显示加载标识。

React.Fragments

这样并不会在DOM中增加额外节点,相当于 render 返回数组元素。

35请简述display: none和visibility: hidden对比的优缺点

36介绍下vuex以及应用的场景***

Vuex 是一个专为 Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到Vue 的官方调试工具 devtools extension ,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。当我们构建中大型SPA(单页面应用)项目时,Vuex则从中具有非常大的作用。

Vuex的应用场景

涉及到非父子组件之间的传值,例如兄弟关系、祖孙关系,甚至更远的关系组件之间的联系,如果使用传统父子组件之间传值的方式时,对开发人员来说可能是噩梦;

中大型单页应用,考虑如何更好地在组件外部管理状态;

39闭包是什么,有什么特性,请简单书写一个简单实例

特性:闭包是能够读取其他函数内部变量的函数,即在外面可以调用函数中的函数的变量,其实他就是将函数内外部连接起来的桥梁

//事例:

40ES5 的继承和 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 关键字,否则报错。

107vue-router

方式 hash history

跳转 this.$router.push()

占位

84动态路由hash history区别

https://www.cnblogs.com/LazyPet/p/12170995.html

前端路由原理?两种实现⽅式有什么区别?

前端路由实现起来其实很简单,本质就是监听 URL 的变化,然后匹配路由规则,显示相应的⻚⾯,并且⽆须刷新⻚⾯。⽬前前端使⽤的路由就只有两种实现⽅式

Hash 模式

www.test.com/#/ 就是 Hash URL ,当 # 后⾯的哈希值发⽣变化时,可以通过 onhashchange 事件来监听到 URL 的变化,从⽽进⾏跳转⻚⾯,并且⽆论哈希值如何变化,服务端接收到的 URL 请求永远是 www.test.com

window.addEventListener(‘hashchange’, () => {

// … 具体逻辑

})

Hash 模式相对来说更简单,并且兼容性也更好

History 模式 History 模式是 HTML5 新推出的功能,主要使⽤ history.pushState和 history.replaceState 改变 URL 通过 History 模式改变 URL 同样不会引起⻚⾯的刷新,只会更新浏览器的历史记录。当⽤户做出浏览器动作时,⽐如点击后退按钮时会触发 popState 事件

两种模式对⽐

Hash 模式只可以更改 # 后⾯的内容, History 模式可以通过 API 设置任意的同源URL

History 模式可以通过 API 添加任意类型的数据到历史记录中, Hash 模式只能更改哈希值,也就是字符串

Hash 模式⽆需后端配置,并且兼容性好。 History 模式在⽤户⼿动输⼊地址或者刷新⻚⾯的时候会发起 URL 请求,后端需要配置 index.html ⻚⾯⽤于匹配不到静态资源的时候

computed 和 watch 区别

computed 是计算属性,依赖其他属性计算值,并且 computed 的值有缓存,只有当计算值变化才会返回内容。

watch 监听到值的变化就会执⾏回调,在回调中可以进⾏⼀些逻辑操作。

所以⼀般来说需要依赖别的属性来动态获得值的时候可以使⽤ computed ,对于监听到值的变化需要做⼀些复杂业务逻辑的情况可以使⽤ watch 。

另外 computer 和 watch 还都⽀持对象的写法,这种⽅式知道的⼈并不多。

keep-alive 组件有什么作⽤

如果你需要在组件切换的时候,保存⼀些组件的状态防⽌多次渲染,就可以使⽤ keepalive 组件包裹需要保存的组件。

对于 keep-alive 组件来说,它拥有两个独有的⽣命周期钩⼦函数,分别为 activated和 deactivated 。⽤ keep-alive 包裹的组件在切换时不会进⾏销毁,⽽是缓存到内存中并执⾏ deactivated 钩⼦函数,命中缓存渲染后会执⾏ actived 钩⼦函数。

41怎么定义vue-router的动态路由?怎么获取传过来的动态参数?

https://blog.csdn.net/m0_48560510/article/details/110354840
进入首页时两次加载一个文档,优化代码当是登录页面跳转过来的才加载,可以通过导航守卫来实现,还可以有三种方法,query传参 params传参和直接路径拼接this.$router.push(’/index?from=login’),说明是从登录页面过来的,带有login的参数

query传参,其实是get传参,在地址栏里会拼接登录地址this.$router.push({ path: '/index', query: {  from: 'login' }})params传参,路径没有进行拼接,但是是由参数的this.$router.push({ name: 'index',不是路径,应该是路由的名称 params: {  from: 'login' }

})
获取参数时用this. r o u t e , route, routeroute是路由实例,而$router是全局路由,整个路由都在里面(11-4)

可以通过queryparam两种方式
区别:query通过url传参,刷新页面还在;params属性页面不在

params的类型:

  1. 配置路由格式:/router/:id

  2. 传递的方式:在path后面跟上对应的值

  3. 传递后形成的路径:/router/123

    // 动态路由params在App.vue中用户在index.js	{	path:"/user/:userid",	component:User,	}
    

    跳转方式:

    // 方法1:按钮// 方法2:this.$router.push({name:'users',params:{uname:wade}})// 方法3:this.$router.push('/user/' + wade)
    

    可以通过$route.params.userid 获取你说传递的值

    query的类型

    1. 配置路由格式:/router,也就是普通配置
    2. 传递的方式:对象中使用query的key作为传递方式
    3. 传递后形成的路径:/route?id=123
//01-直接在router-link 标签上以对象的形式档案/*    02-或者写成按钮以点击事件形式        */  //点击事件 profileClick(){   this.$router.push({            path: "/profile",            query: {                  name: "kobi",                  age: "28",                  height: 198            }      }); 

跳转方法:

// 方法1:按钮// 方法2:this.$router.push({name:'users',params:{uname:wade}})// 方法3:this.$router.push('/user/' + wade)

可以通过$route.query 获取你所传递的值

44vue-router有哪几种导航钩子,导航钩子的作用是什么?

vue-router提供的导航钩子主要用来拦截导航,让它完成跳转或取消。

导航钩子的分类

  • 全局守卫 简单点说就是触发路由就会触发这些钩子函数。钩子函数执行顺序包括beforeEach、beforeResolve、afterEach三个。
  • 路由独享守卫
  • 局部守卫

93如何配置React-Router

yarn add react-router-dom

在最外面的App.js里

import { BrowserRouter, Route } from ‘react-router-dom’;

在组件的render()里

	
home
}>
detail
}>

代表的是路由说明里面内容要用路由了,它里面只能有一个children

Route代表的是路由规则

exact指只有路径完全相同才显示,否则只要路径包含就显示(8-1)

单页面应用就不能用

要使用Link

import { Link } from ‘react-router-dom’;

注意:使用Link标签的组件必须放在总的文件内部(8-10)

96react-router⾥的标签和标签有什么区别

对比,Link组件避免了不必要的重渲染 react-router:只更新变化的部分从而减少DOM性能消耗

react的创新之处在于,它利用虚拟DOM的概念和diff算法实现了页面的“按需加载”

42Vue引入了虚拟Dom主要解决了什么问题

43输出结果

var test = (function (a) {	
    this.a = a;	
    return function (b) {		
        return this.a + b;	
    }}(function(a, b) {	
        return a;
}(1, 2)));
console.log(test(4));

输出结果:5(1+4)

(function(a, b) {	
	return a;
}(1, 2))
回的是1,传给atest相当于
test = function (b) {	
	return this.a + b;
}b是4

45vue-loader是什么?使用它的途径有哪些?

一、vue-loader作用:

解析和转换.vue文件。提取出其中的逻辑代码 script,样式代码style,以及HTML 模板template,再分别把他们交给对应的loader去处理

二、用途

js可以写es6,style样式可以写scss或less、template可以加jade等

三、

css-loader:加载由vue-loader提取出的CSS代码

vue-template-compiler:把vue-loader提取出的HTML模板编译成可执行的javascript代码

30请写出删除数组元素的几种原生算法

splice(index,len,[item]) 注释:该方法会改变原始数组。注:concat不会改变原数组,需要有个变量来承接一下。

delete arr[1] delete删除掉数组中的元素后,会把该下标出的值置为undefined,数组的长度不会变

46delete和Vue.delete删除数组的区别

delete只是被删除的元素变成了 empty/undefined 其他的元素的键值还是不变。

Vue.delete 直接删除了数组 改变了数组的键值。

50使用选择排序或冒泡排序方法对数组let arr = [3, 5, 1, 9, 4, 2]进行排序

52介绍一下Vue组件的生命周期

https://www.cnblogs.com/qidh/p/11431998.html

https://www.cnblogs.com/wangjiachen666/p/9497749.html


53使用CSS的flexbox布局,不能实现以下哪一个效果:

D、多个宽高不等的元素,实现无缝瀑布流布局

答案:D

54下面关于this的说法错误的是A

A.严格模式下,普通函数中没有直接调用者的函数中this指向window

B.普通函数中this指向它的直接调用者

C.普通函数中使用call绑定的this指向绑定的对象

D.箭头函数中的this指向定义它时所处的宿主对象

A为undefined

55new Date(‘yyyy-mm-dd’)返回本地时间,new Date(‘yyyy/mm/dd’)返回UTC时间

56返回a1 undefined a2

var obj1 = {  a: 'a1',  b: function () {return this.a},  c: function (obj) {    obj = {a : 'a2'};    return this.a;  }}var getFunctionB = obj1.b;var res1 = obj1.b();var res2 = getFunctionB();var res3 = obj1.c(obj1);

57

var dateStr = 'Friday';(function () {  if (typeOf dateStr === 'undefined') {    var dateStr = 'Staurday';    console.log('Hello' + dateStr);  }else {    console.log('Happy' + dateStr);  }})();输出’Hello Staurday’var str = 'World!';    (function (name) {  if (typeof name === 'undefined') {    var name = 'Jack';    console.log('Goodbye ' + name);  } else {    console.log('Hello ' + name);  }})(str);输出Hello World 因为name已经变成函数内局部变量

58ES6内部使用严格相等运算符(===),判断一个位置是否有值。所以,如果一个数组成员不严格等于undefined,默认值是不会生效的。

var [x, y = “b”] = [“a”, undefined];//x = “a”, y = “b”

var [x = 1] = [undefined];//x = 1

var [y = 1] = [null];//y = null

59冒泡排序、选择排序、快速排序

排序算法的稳定性,通俗地讲就是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。在简单形式化一下,如果Ai = Aj, Ai原来在位置前,排序后Ai还是要在Aj位置前。

60div嵌套,居中布局有几种方式,各自的适合范围和问题

margin: auto;

flex

绝对定位,反方向平移宽和高的一半

table vertical-align: middle;

20 如何垂直居中⼀个浮动元素***?

/**⽅法⼀:已知元素的⾼宽**/
\#div1{
 background-color:#6699FF;
 width:200px;
 height:200px;
 position: absolute; //⽗元素需要相对定位
 top: 50%;
 left: 50%;
 margin-top:-100px ; //⼆分之⼀的height,width
 margin-left: -100px;
}
//不知道宽高
  width: 78px;
  height: 78px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translateX(-50%) translateY(-50%);
//
display:flex;
justify-content: center;
align-items: center; 
/**⽅法⼆:**/
\#div1{
 width: 200px;
 height: 200px;
 background-color: #6699FF;
 margin:auto;
 position: absolute; //⽗元素需要相对定位***

如何垂直居中⼀个 ?(⽤更简便的⽅法。)

#container {
	display: table-cell;
	text-align: center;
	verticle-align: middle;
}
水平居中
  • 行内元素: text-align: center
  • 块级元素: margin: 0 auto
  • position:absolute +left:50%+ transform:translateX(-50%)
  • display:flex + justify-content: center
垂直居中
  • 设置line-height 等于height
  • position:absolute +top:50%+ transform:translateY(-50%)
  • display:flex + align-items: center
  • display:table+display:table-cell + vertical-align: middle;

62http返回的状态有几种,403、401、302、304

64输入1返回2,输入2返回1,有几种方法

65自适应布局几种方法,使用范围,左侧200px,右侧自适应

71sort排序

//升序arr.sort((a, b) => {return a-b;})

79不用组件怎么实现轮播图,当鼠标停留在图片上时怎么实现图片轮播不动

可以使用js和无序列表的方式;CSS动画过渡的方式,仔细看这两种实现方式的代码

https://www.jianshu.com/p/bd1f34e7e953

80v-if v-show 区别

v-show 只是在 display: none 和 display: block 之间切换。⽆论初始条件是什么

都会被渲染出来,后⾯只需要切换 CSS , DOM 还是⼀直保留着的。所以总的来说 v-show 在初始渲染时有更⾼的开销,但是切换开销很⼩,更适合于频繁切换的场景。

v-if 的话就得说到 Vue 底层的编译了。当属性初始为 false 时,组件就不会被渲染,直到条件为 true ,并且切换条件时会触发销毁/挂载组件,所以总的来说在切换时开销更⾼,更适合不经常切换的场景。并且基于 v-if 的这种惰性渲染机制,可以在必要的时候才去渲染组件,减少整个⻚⾯的初始渲染开销。

81key作用

85 都有哪些指令

86如何判断类型

87置换元素 哈希 require.js common.js AMD CMD

置换元素是指根据标签和属性来决定元素的具体显示内容,置换元素在其显示中生成了框,这就是有的内嵌元素能够设置宽高的原因。元素img input textarea select object。大多数元素都是不可置换。label p

一个对象在其生命周期内,保持不变就是可哈希的hashable,例如字符串。可改变的就是不可哈希的unhashable,列表

require.js是js的轻量化框架,用于提高代码质量

CommonJS、AMD、CMD是用于JavaScript模块管理的三大规范

CommonJS定义的是模块的同步加载,是一个更偏向于服务器端的规范(也可以在浏览器中使用),主要用于Nodejs,根据CommonJS规范,一个单独的文件就是一个模块,加载模块使用require()方法,该方法读取一个文件并执行,最后返回文件内部的exports对象。

AMD和CMD则是定义模块异步加载适用于浏览器端,都是为了 JavaScript 的模块化开发,(这里说一下为什要有异步加载,因为浏览器如果使用common.js同步加载模块的话,就会导致性能等问题,所以针对这个问题,又出了一个规范,这个规范可以实现异步加载依赖模块)

AMD规范会提前加载依赖模块,AMD规范是通过requireJs 在推广过程中对模块定义的规范化产出。RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。推崇依赖前置。AMD 推荐的⻛格通过返回⼀个对象做为模块对象

CMD规范会延迟加载依赖模块, CMD 规范是 SeaJs 在推广过程中对模块定义的规范化产出。推崇依赖就近。 CommonJS 的⻛格通过对module.exports 或 exports 的属性赋值来达到暴露模块对象的⽬的

88对async、await的理解,内部原理

async函数就是generator函数的语法糖。

async函数,就是将generator函数的*换成async,将yield替换成await。

async函数对generator的改进

(1)内置执行器,不需要使用next()手动执行。

(2)await命令后面可以是Promise对象或原始类型的值,yield命令后面只能是Thunk函数或Promise对象。

(3)返回值是Promise。返回非Promise时,async函数会把它包装成Promise返回。(Promise.resolve(value))

作用

异步编程的终极解决方案。

通俗理解

async/await,就是异步编程回调函数写法的替代方法。(使代码以同步方式的写法完成异步操作)函数执行时,一旦遇到await就会返回。等到触发的异步操作完成(并且调用栈清空),再接着执行函数体内后面的语句。

await语句后面的代码,相当于回调函数。(即:await的下一行开始,都视作回调函数的内容)

回调函数会被压入microtask队列,当主线程调用栈被清空时,去microtask队列里取出各个回调函数,逐个执行。

91redux的设计思想 接⼊redux的过程 绑定connect的过程

Redux是什么呢?一个状态管理工具。那是干嘛用的呢?都知道,React可以进行单页应用(SPA)的开发,可以对页面中各个模块进行分割形成组件,而组件之间就避免不了事件的传递或数据的交互,那Redux就是用来对这些组件的状态进行管理的。

https://segmentfault.com/a/1190000008736866

92webpack介绍

WebPack 是⼀个模块打包⼯具,你可以使⽤ WebPack 管理你的模块依赖,并编绎输出模块们所需的静态⽂件。它能够很好地管理、打包 Web 开发中所⽤到的 HTML 、Javascript 、 CSS 以及各种静态⽂件(图⽚、字体等),让开发过程更加⾼效。对于不同类型的资源, webpack 有对应的模块加载器。 webpack 模块打包器会分析模块间的依赖关系,最后⽣成了优化且合并后的静态资源

95promise、async有什么区别

函数前面多了一个async关键字。await关键字只能用在async定义的函数内。async函数会引式返回一个promise,改promise的resolve值就是函数return的值。

简洁:使用async和await明显节约了不少代码,不需要.then,不需要写匿名函数处理promise的resolve的值,不需要定义多余的data变量,还避免了嵌套代码。

async/await让try/catch 可以同时处理同步和异步错误。try/catch不能处理JSON.parse的错误,因为他在promise中。此时需要.catch,这样的错误处理代码非常冗余。并且,在我们的实际生产代码会更加复杂

条件语句

97cookie放哪⾥

设置过期时间失效(只要设置了过期时间cookie就会存储在硬盘里面)

当会话结束时失效,即关闭浏览器窗口(如果没有设置Expires,cookie就会存储在内存里面)

103 es5异步编码的方式

回调函数,这是异步编程最基本的方法。

事件监听,另一种思路是采用事件驱动模式。任务的执行不取决于代码的顺序,而取决于某个事件是否发生。

发布/订阅

Promises对象,Promises 对象是CommonJS 工作组提出的一种规范,目的是为异步编程提供统一接口。

https://cloud.tencent.com/developer/article/1499717

es6

promise generator async

104js常见的内存泄漏

意外的全局变量引起的内存泄露leak=“xxx”;//leak**成为一个全局变量,不会被回收

闭包

没有清理的DOM元素引用

定时器的第一个参数不是函数而是字符串

循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)

子元素存在引起的内存泄露

可⽤ chrome 中的 timeline 进⾏内存标记,可视化查看内存的变化情 况,找出异常点。

怎样避免内存泄露

1)减少不必要的全局变量,或者生命周期较长的对象,及时对无用的数据进行垃圾回收;

2)注意程序逻辑,避免“死循环”之类的 ;

3)避免创建过多的对象 原则:不用了的东西要及时归还。

https://blog.csdn.net/michael8512/article/details/77888000

105前端工程化

模块化 js scss

组件化

规范化 HTML css js规范 命名规范 前后端接口规范

自动化

106函数调用的方式

//方法调用模式var blogInfo={  blogId:123,  blogName:"werwr",  showBlog:function(){alert(this.blogId);}};blogInfo.showBlog();//函数调用模式var myfunc = function(a,b){  return a+b;}alert(myfunc(3,4));//构造器调用模式var myfunc = function(a){  this.a = a;};myfunc.prototype = {  show:function(){alert(this.a);}}var newfunc = new myfunc("123123123");newfunc.show();//apply,call调用模式var myobject={};var sum = function(a,b){  return a+b;};var sum2 = sum.call(myobject,10,30); //var sum2 = sum.apply(myobject,[10,30]); alert(sum2);

108动画的例子,好好看一下,会手写

#div:hover {} //hover的位置

110

var cityData = [{

​ id: 1,

​ name: ‘广东省’,

​ children: [{

​ id: 11,

​ name: ‘深圳’}]

}]

//直接想到用递归来做吧~,先获取最外层的元素,判断id是否相等,不相等就继续判断是否含有子节点,然后继续递归循坏const recursion = (cityData, id) => {    if (!cityData || !cityData.length) {    	return;    }    //先循坏cityData    for (let i = 0; i < cityData.length; i++) {        const childs = cityData[i].children;        if (cityData[i].id === id) {        	result = cityData[i].name;        }        if (childs && childs.length > 0) {        	recursion(childs, id);        }    }      return result;}console.log(recursion(cityData, 122))//灵芝

113vue模板语法底层是怎么实现的

Vue的MVVM模型讲的是 model(数据模型),view(视图、模板),VM-> ViewModel,VM是M和V之间的桥梁

响应式 :vue如何监听到data的每个属性变化?

利用Object.defineProperty定义属性,将data里面的属性代理到vm上

模板解析: vue的模板如何被解析,指令如何处理?

  1. vue里面为什么要解析模板?

这个模板里的html有逻辑,v-for, v-if等等,最终必须解析成html来显示,模板最终必须转换成 JS 代码

因为:

有逻辑(v-if v-for),必须用 JS 才能实现( 图灵完备)

转换为 html 渲染页面,必须用 JS 才能实现

因此,模板最重要转换成一个 JS 函数

  1. render函数

with 用法:with 语句可以方便地用来引用某个特定对象中已有的属性,但是不能用来给对象添加属性。要给对象创建新的属性,必须明确地引用该对象。

render 函数

VUE一般使用template来创建HTML,然后在有的时候,我们需要使用javascript来创建html,这时候我们需要使用render函数。

Vue的实现流程

1、首先模板解析器解析成render函数

2、响应式监听

3、将数据渲染进模板里

4、data属性变化,触发render

114 vue中action和mutation的区别

action是处理异步任务的或者繁琐的同步任务的

mutation是处理同步任务的

115https是怎么加密的

对称加密

非对称加密

对称加密+非对称加密结合

https://blog.csdn.net/qq_29996285/article/details/84284524

116 rem em相关知识(看书)

117url页面流程

浏览器先查找当前的url是否存在缓存,并比较缓存是否过期

没有缓存,浏览器将当前的url发送给DNS服务器解析url对应的IP地址

根据IP地址建立TCP连接

HTTP发起请求

服务器处理请求,浏览器接收HTTP响应

渲染页面,构建DOM树

关闭TCP连接

118 vue中nextTick() process.nextTick

vue中nextTick()方法是将回调函数延迟在下一次dom更新数据后调用,简单的理解是:当数据更新了,在dom中渲染后,自动执行该函数,

process.nextTick()的意思就是定义出一个动作,并且让这个动作在下一个事件轮询的时间点上执行。

function foo() {
    console.error('foo');
}
process.nextTick(foo);
console.error('bar');
//先输出'bar',再输出'foo'

119HTTP / 2.0

因为浏览器会有并发请求限制,在 HTTP / 1.1 时代,每个请求都需要建⽴和断开,消耗了好⼏个 RTT 时间,并且由于 TCP 慢启动的原因,加载体积⼤的⽂件会需要更多的时间
在 HTTP / 2.0 中引⼊了多路复⽤,能够让多个请求使⽤同⼀个 TCP 链接,极⼤的加快了⽹⻚的加载速度。

并且还⽀持 Header 压缩,进⼀步的减少了请求的数据⼤⼩

120查找两个字符串的最长公共子串的JavaScript函数

function findLongestCommonStr(s1, s2) {
    var commonStr = '', L1 = s1.length, L2 = s2.length;
    var shortStr = L1>L2 ? s2 : s1;
    var longStr = L1>L2 ? s1 : s2;
    var strLen = shortStr.length;
    for (let j = strLen; j > 0; j--) {
        for (let i = 0, k = j; i <= strLen - j; i++, k++) {
            commonStr = shortStr.subString(i, k);
            if (longStr.indexOf(commonStr) >= 0) return commonStr;
        }
    }
    return '';
}

121

//主线程直接执行console.log('1');//丢到宏事件队列中setTimeout(function() {    console.log('2');    process.nextTick(function() {        console.log('3');    })    new Promise(function(resolve) {        console.log('4');        resolve();    }).then(function() {        console.log('5')    })})//微事件1process.nextTick(function() {    console.log('6');})//主线程直接执行new Promise(function(resolve) {    console.log('7');    resolve();}).then(function() {    //微事件2    console.log('8')})//丢到宏事件队列中setTimeout(function() {    console.log('9');    process.nextTick(function() {        console.log('10');    })    new Promise(function(resolve) {        console.log('11');        resolve();    }).then(function() {        console.log('12')    })})//1 7 6 8 2 4 3 5 9 11 10 12
async function async1() {  console.log('async1 start')  await async2()  console.log('async1 end')} async function async2() {  console.log('async2')} console.log('script start')setTimeout(function() {  console.log('setTimeout')}, 0) async1();    new Promise( function( resolve ) { console.log('promise1') resolve();} ).then( function() { console.log('promise2')} ) console.log('script end')script startasync1 startasync2promise1script endpromise2async1 endsetTimeout首先,事件循环从宏任务(macrostack)队列开始,这个时候,宏任务队列中,只有一个 script (整体代码)任务。从宏任务队列中取出一个任务来执行。首先执行 console.log('script start'),输出 ‘script start'遇到 setTimeout 把 console.log('setTimeout') 放到 macrotask 队列中执行 aync1() 输出 ‘async1 start' 和 'async2' ,把 console.log('async1 end') 放到 micro 队列中执行到 promise ,输出 'promise1' ,把 console.log('promise2') 放到  micro 队列中执行 console.log('script end'),输出 ‘script end'macrotask 执行完成会执行 microtask ,把 microtask quene 里面的 microtask 全部拿出来一次性执行完,所以会输出 'async1 end' 和 ‘promise2'开始新一轮的事件循环,去除执行一个 macrotask 执行,所以会输出 ‘setTimeout'

122哪些数组方法改变自身数组:splice sort pop push

哪些不改变:concat

124对于实现双向数据绑定,Object.defineProperty()有什么缺点?有没有更好的方法来实现?

Object.defineProperty()有以下2个非常明显的缺点:

(1)无法监听数组的变化。

(2)只能劫持对象的属性,无法劫持一个完整的对象。

对于实现双向数据绑定,更好的方法是使用Proxy对象来实现,如何实现

两种方式都要手撕代码

129定义一个矩形类Rectangle,它是由宽width和长height两个参数构造的,然后在类中定义一个getArea()方法,用来计算矩形的面积。
Class Rectangle {    constructor(width, height) {        this.width = width;        this.height = height;    }    getArea() {        return this.width * this.height;    }}

130vue的作用和核心功能

Vue是渐进式的JavaScript框架

优点:压缩后体积小,效率高(虚拟DOM)、双向绑定、成熟框架

功能:v-bind v-on v-if v-show v-text v-html 组件 双向绑定

132URL URI区别

URI 是统一资源标识符,而 URL 是统一资源定位符。

每个 URL 都是 URI,但不一定每个 URI 都是 URL。这是因为 URI 还包括一个子类,即统一资源名称 (URN),它命名资源但不指定如何定位资源。

133ajax过程,代码

134 email正则表达式

/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/

137 UDP和TCP的区别

TCP和UDP都是传输层的协议

UDP提供了不可靠的无连接传输服务;TCP提供了可靠的面向连接的字节流传输协议

138给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标

var towSum = function(nums, target){  for(let i=0, len = nums.length; i< len; i++) {    if(nums.indexOf(target - nums[i]) > -1 ) {      return [i, nums.indexOf(target - nums[i])]    }  }}//var towSum = function(nums, target){  let obj = {};  for(let i=0, len=nums.length; i< len; i++){    let mult = target - nums[i];    if(mult in obj){      return [obj[mult], i];    }    obj[nums[i]] = i;  }}//var towSum = function(nums, target){  for(let i=0, len = nums.length; i

140 react中pureComponent的作用,处理异步操作用什么(react-thunk的作用,dispatch的升级)

对于多个组件的connect和store进行连接,一旦store内部修改了,那么每个组件都会重新渲染,也就是每个组件的render都会重新执行,解决这个问题可以使用之前的shouldComponentUpdate,react内部有PureComponent解决这个问题,只要把之前的引入包括使用Component的地方都改为PureComponent
import React, { PureComponent } from ‘react’;
因为使用了immutable.js这个框架,PureComponent和immutable.js能完美结合,但是如果不使用immutable.js就使用PureComponent的话,那么会遇到一些底层问题的坑,所以如果不使用immutable.js,最好自己写一个shouldCompomentUpdate来进行代码优化,不要使用PureComponent

141 vue中父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted

142 max-age=0

no-cache

如果request headers中,Cache-Control为no-cache。表示不管服务端有没有设置Cache-Control,都必须从重新去获取请求。 浏览器缓存,但是认为是过期缓存

max-age=0

max-age=0表示不管response怎么设置,在重新获取资源之前,先检验ETag/Last-Modified

不管是max-age=0还是no-cache,都会返回304(资源无修改的情况下),no-store才是真正的不进行缓存。

144闭包的好处

1.减少全局变量

//达到每次调用函数add(),a都不断加1

function add(){	var a = 0;	a++;	alert(a);}add();add();//这样做每次调用a都从0开始//这样可以实现累加效果var a = 0;function add() {	a++;	alert(a);}add();add();//但这样做就增加全局变量//改为闭包的方式function f(){	var a = 0;	return function(){		a++;		alert(a);	}}var result = f();result();result();

2.减少传递给函数的参数数量

//实现例如基数为2,最大数为3,返回值为2+ 1+2+3的值

//可以这样实现

function add(base,max){…}

//用闭包function calFactory(base){	return function(max){		var total = 0;		for(var i = 1, i <= max, i++ ){			total +=i;		}		return total + base;	}}var adder = calFactory(2);adder(3);//8//2+1+2+3adder(4);//12//2+1+2+3+4

3.起到封装的作用

(function(){	var m = 0;	function getM(){//闭包		return m;	} 	function setM(){//闭包		m = val;	}	window.g = getM;//通向外部的接口	window.s = setM;})();//立即调用的匿名函数s(12);alert(g());
闭包的注意事项:

1.对于捕获到的变量只是个饮用,不是复制

function f(){	var num = 1;	function g(){		alert(num);//引用父的num	}	num++;	g();//2}

2.父函数每调用一次,会产生不同的闭包

function f(){	var num = 1;	return function(){		num++;		alert(num);	}}var result1 = f();//由函数的预处理可知,每次调用一个函数的时候会创建一个新的词法环境result1();//2result1();//3var result2 = f();//创建一个新的词法环境result2();//2result2();//3

3.循环中的问题


1
2
3
for(var i = 1;i <=3;i++){ var ele = document.getElementById(”i”); ele.onclick = function(){ alert(i); } } //点击1 2 3 都会弹出4,因为没有块级作用域,所以i相当于全局变量 //解决办法,可以用闭包
1
2
3
(for(var i = 1;i <=3;i++){ var ele = document.getElementById(”i”); ele.onclick = (function(id){ return function(){ alert(id); } })(i);//每次点击1或2或3都会立即执行函数,从而达到点击几弹出几的效果 //每被调用一次函数,父函数的i都会被捕获,都会重新产生一个闭包

145this

this永远指向对象

this可以直接写在全局里面,并且此时永远指向window对象;this也可以写在函数里面,此时氛围三种情况:

第一种情况:

var ele = document.getElementById(”id”);
ele.addElementListener(”click”,function{
	console.log(this);//这种情况this永远指向引发事件的对象ele
})

第二种情况:

//this的指向是运行时决定,不是编写代码时决定

//运行时函数是谁调用的,this就指向谁

var o = {	name:”nice”;	print:function(){		console.log(this.name);	}}o.print();//nice//函数是o调用的var ff = o.print;ff();//undefined//此时相当于window.ff(),函数是window调用的

第三种情况:

function f(){
	this.name = “nice”;
}

上面第二种情况改变了this的指向,还可以使用call或apply或bind改变this指向,call和apply和bind都是函数对象都会有的东西

call和apply的区别:

传参的时候call使用参数列表的形式,一个一个地传,而apply使用参数数组的形式

var o = {
	name:”nice”;
	print:function(){
		console.log(this.name);
	}
}
var ff = o.print;
ff();//undefined
this.name = “global”;
this.age = 22;
ff();//global
function log(a,b){
	console.log(this[a]);
	console.log(this[b]);
}
log(”name”,”age”);//global 22
log.call(o,”name”);//nice//改变了this的指向,相当于o.log(“name”)
log.call(o,”name”,”age”);//nice undefined//undefined因为在o对象中没有age变量
log.apply(o,[’’name”,”age”])//nice undefined

146算法题:去除字符串中的连续重复字母

用迭代

var s = "1122333455";var cc = s.match(/(\d)\1+/g);    //11,22,333,55 s1 = s.replace(cc[i], "");

147js 不增加变量,怎么实现两个变量值的互换

ES6的解构let a = 1,b = 2;[a, b] = [b, a];var a = 1,b = 2;a = [a, b];b = a[0];a = a[1];

148js中的基本类型与包装类型

ECMAScript 提供了 3 个特殊的引用类型:Boolean、Number和 String。这些类型与其他引用类型相似,但同时也具有与各自的基本类型相应的特殊行为。

实际上,每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而能够调用一些方法来操作这些数据。

包装对象:
包装对象,就是当基本类型以对象的方式去使用时,JavaScript会转换成对应的包装类型,相当于new一个对象,内容和基本类型的内容一样,然后当操作完成再去访问的时候,这个临时对象会被销毁,然后再访问时候就是undefined。number,string,boolean都有对应的包装类型。 number,string,boolean都有对应的包装类型

因为有了基本包装类型,所以JS中的基本类型值可以被当作对象来访问;
基本类型特征:
1.每个包装类型都映射到同名的基本类型;
2.在读取模式下访问基本类型值时,就会创建对应的基本包装类型的一个对象,从而方便了数据操作;
3.操作基本类型值的语句一经执行完毕,就会立即销毁新创建的包装对象;
引用类型和基本包装类型的主要区别就是对象的生存期;
自动创建的基本包装类型的对象,则只存在于一行代码的执行瞬间,然后立即被销毁;
这意味着我们不能在运行时为基本类型值添加属性和方法;

149 document.write(eval(“2+2”))//4

150 域名分发

151自适应布局的方法

@media

meta viewport

html标签中设置font-size: …px,然后下面的尺寸都用rem进行设计 62.5%

vm vh

152数组乱序

function reArr (arr) {    return arr.sort(() => {    	return Math.random() - 0.5;    })}// console.log(reArr([2, 3, 1, 5]));function isReArr (n, reArr, arr) {    var arr1 = [0, 0, 0, 0];    var length = arr.length;    for (var i = 0; i < n; i++) {        var arr2 = reArr(arr);        for (var j = 0; j < length; j++) {        	arr1[j] += arr2[j];        }    }    arr1.forEach((item) => {    return item / n;    })}isReArr(500, reArr, [2, 3, 1, 5]);数组乱序function reArr (arr) {    return arr.sort(() => {    	return Math.random() - 0.5;    })}var list = [1,2,3,4,5,6,7,8,9,10];var newlist = [];for(var i=0;i<10;i++){    var num =  Math.floor(Math.random()*list.length) ;    newlist.push(list[num]);    list.splice(num,1)}//  forEach遍历,随机生成下标,交换位置function disorderArr(arr) {       arr.forEach((e, i, a) => {         let randomIndex = Math.floor(Math.random()*list.length)          let temp = a[randomIndex]         a[randomIndex] = a[i]         a[i] = temp     })     return arr }// 洗牌原理:从数组的最后位置开始,从前面随机一个位置,对两个数进行交换,直到循环完毕 function shuffleSort(arr) {     let i = arr.length - 1     while(i>0) {         let rIndex = Math.floor(Math.random()*i)         let temp = arr[rIndex]         arr[rIndex] = arr[i]         arr[i] = temp         i--     }     return arr }

153输出结果

foo ();function foo () {	console.log("foo1");}foo ();function foo () {	console.log("foo2");}foo ();//foo2 foo2 foo2

154

var abc = function foo () {}console.log(typeof(foo));//undefinedconsole.log(typeof(foo()));//报错console.log(typeof(abc));//functionconsole.log(typeof(abc()));//undefined,因为函数没有返回值

155 http中put和patch的区别

PATCH方法是新引入的,是对PUT方法的补充,用来对已知资源进行局部更新

156

const d = new Date();const year = d.getFullYear();let month = (d.getMonth() + 1).toString().padStart(2, "0");let day = d.getDate().toString().padStart(2, "0");const time = `${year}-${month}-${day}`;console.log(time);const d = new Date();const year = d.getFullYear();let month = d.getMonth() + 1;let day = d.getDate();if (month.toString().length < 2) {    month = "0" + month;}if (day.toString().length < 2) {    day = "0" + day;}const time = year + "-" + month + "-" + day;console.log(time);

157typeof typeof 123 返回的是string类型

var temp=typeof 123;//>temp=‘number’
typeof typeof 123;//
>typeof ‘number’==>‘string’

158getElementById()返回的是什么?

“object HTMLDivElement”,即 HTMLDivElement 对象

159 ts js TypeScript和JavaScript的对比:

typescript ts是微软牵头主导的,主要来自C#
ts需要静态编译,它提供了强类型与更多面向对象的内容。
ts最终仍要编译为弱类型的js文件,基于对象的原生的js,再运行。故ts相较java/C#这样天生面向对象语言是有区别和局限的

TypeScript是一个应用程序级的JavaScript开发语言。(这也表示TypeScript比较牛逼,可以开发大型应用,或者说更适合开发大型应用)
TypeScript是JavaScript的超集,可以编译成纯JavaScript。这个和我们CSS离的Less或者Sass是很像的
TypeScript跨浏览器、跨操作系统、跨主机、且开源。由于最后他编译成了JavaScript所以只要能运行
TypeScript始于JavaScript,终于JavaScript。遵循JavaScript的语法和语义
TypeScript提供了类、模块和接口,更易于构建组件和维护。typescript与javascript关系
typescript是javascript的超集,即你可以在ts中使用原生js语法,扩展了javascript的语法。

typescript必须声明变量类型如:var message = “article”; //javascriptvar message:string = “article”; //typescript函数声明不同//javascriptfunction test(){return ‘article’}//typescript:需声明返回值类型function test():string{return ‘article’}基本数据类型不同:javascript:boolean类型、number类型、string类型、array类型、undefined、nulltypescript:除了上面类型外,还包含tuple类型(元组类型)、enum类型(枚举类型)、any类型(任意类型)ts增加的语法静态类型:有利于检查代码错误,运行前检查类型错误函数缺省参数值:类:模块:可以把声明、数据、函数和类封装在模块中接口:类型注解:通过类型注解来增加编译时静态类型检查

160将两个有序的数组合并成一个有序数组

function arrSort(arr1, arr2) {    var [i,j] = [0,0];    let newArr = [];    while(i < arr1.length || j  arr2[j]) {            newArr.push(arr2[j])            j++        } else {        	//i或者j到头了,进行判断一下            if(arr1[i] !== undefined) newArr.push(arr1[i]);            if(arr2[j] !== undefined) newArr.push(arr2[j]);            i++;            j++        }    }    return newArr}

23请简述数组的基础操作读写与新增的性能对比

数组性能我首先想到的就是从两方面,一是数组的迭代二是向数组中添加元素.

迭代的话是最普通的for循环效率最高,而且普通的for循环还可以继续优化;向数据中添加元素是用索引的方式添加元素最快,而且不同的浏览器各种方法效率有差异.但是利用索引添加元素最快无疑.

map和forEach对比:

1、map速度比foreach快

2、map会返回一个新数组,不对原数组产生影响,foreach不会产生新数组,foreach返回undefined

3、map因为返回数组所以可以链式操作,foreach不能

4, map它会返回⼀个新的数组,所以需要有 return 值,如果没有,会返回 undefined ;而foreach里用return不起作用,foreach不能用break,会直接报错。

  1. map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
  2. map() 方法按照原始数组元素顺序依次处理元素。
  3. 注意: map() 不会对空数组进行检测。
  4. 注意: map() 不会改变原始数组。

161正则表达式需要转义的字符

. | $ ? * + ^ \ 转义需要用这个 ( ) [ ] { }

162 Tab选项卡的实现、flex知识、懒加载、吸顶功能

图片懒加载

一张图片就是一个标签,浏览器是否发起请求图片是根据\的src属性,所以实现懒加载的关键就是,在图片没有进入可视区域时,先不给的src赋值,这样浏览器就不会发送请求了,等到图片进入可视区域再给src赋值。

元素到浏览器顶部的距离 e.offsetTopwindow.innerHeight;//获取可视高度(屏幕高度)var scrollHeight = document.documentElement.scrollTop || document.body.scrollTop;//获取滚动的值if ((viewHeight + scrollHeight) > 元素到浏览器顶部的距离) {	设置一个定时器,制造懒加载的延迟加载的效果}

提高首屏的加载速度,提高用户体验,减小带宽
npm i vue-lazyload -s
import VueLazyload from ‘vue-lazyload’;
Vue.use(VueLazyload)或者
Vue.use(VueLazyload, {
error: ‘dist/error.png’,图片不存在时展示的错误图片
load: ‘dist/loading.gif或者.svg也行’,图片没加载出来时显示的样式
})还有其他options
< img v-load=“图片路径”/>

吸顶功能

谷歌获取滚动的高度
document.documentElement.scrollTop
Y轴偏移量window.pageYOffset和上面是一样的
IE浏览器document.body.scrollTop
这三个总归有一个是能取到的

163Object.assign实现

Object.myAssign = function (target, ...src) {  for (let i = 0; i < src.length; i++) {    if (src[i] !== null || src[i] !== undefined) {      // 过滤掉源对象为null和undefined的情况      for (let key in src[i]) {        // in运算符会查找原型对象上的可枚举属性,所以需要通过Object.prototype.hasOwnProperty方法过滤掉对象原型对象上的属性        if (src[i].hasOwnProperty(key)) {          target[key] = src[i][key];        }      }     }  }  return target}

164

const p = Promise.resolve(1);p.then(console.log)p.then(console.log)//输出结果  1  1

165

var a = new Array(1, 1, 1);//[1 1 1]var a = new Array(5);//长度为5的空数组var a = [1, 1, 1]//报错

166冒泡排序具体的次数

总的比较次数=(n-1)+(n-2)+.+1=n(n-1)/2

167原生indexOf的实现

function MyIndexOf(str2,str1,n){//n为起始位置    let i;//循环变量    let len1=str1.length;//子串长度    let len2=str2.length;//父串长度    if(n==undefined ||n==null||n<=-1) {//没有传入起始位置时,从第一位开始        i=0;    }else if(n>len2-1){//如果起始位置大于字符串最后一位,返回-1,不存在        return -1;     }else{//如果不存在上述2种情况,从第n位开始        i=n;    }    if(len1>len2){//如果子串长大于父串,那么肯定不存在,返回-1        return -1;    }else if(len1==len2){//如果相等,就对比2个字符串的内容        if(str1==str2){//如果内容相等,那么就是从第一位开始,返回0            return 0;        }else{//长度相等,内容不相等,那么肯定不存在啦            return -1;        }    }else{        let str21='';        while(i

168

阻止默认事件:

e.preventDefault()

e.returnValue = false (IE)

阻止冒泡:

e.stopPropagation()

e.cancelBubble = true (IE)

169

substr(start,length)是从起始索引号开始提取指定长度的字符串;

substring(start,stop)是提取字符串中两个指定索引号之间的字符;(跟Java中一样),数学上相当于提取 [start,stop) 之间的字符。

170

执行上下文有且只有三类,全局执行上下文,函数上下文,与eval上下文

https://www.cnblogs.com/echolun/p/11438363.html

171请用原生 js 实现一个函数,给页面制定的任意一个元素添加一个透明遮罩(透明度可变,默认 0.2),使这个区域点击无效,要求兼容 IE8+及各主流浏览器

 

https://blog.csdn.net/CareChere/article/details/51312215

offsetLeft offsetWidth

https://blog.csdn.net/willard_cui/article/details/81712989

172

Promise.reject(2).catch(r = > {	console.log('catch1');//捕获到错误,执行}).then(v => {//错误已经被捕获,后面的'then'都顺序执行,且	console.log('then1');}, r => {	console.log('catch2');}).catch(r => {	console.log('catch3');//前面没有未捕获的错误,未执行}).then(v => {	console.log('then2');}, r => {	console.log('catch4');})//catch1  then1  then2

173斐波那契数列的其他实现形式

//使用循环迭代方式实现function fb2(n){    var res1 = 1;    var res2 = 1;    var sum;      var sum = res2;    for(var i = 2;i < n;i ++){        sum = res1 + res2;        res1 = res2;        res2 = sum;    }    return sum;}    //还可以用数组存数据的方式

https://www.cnblogs.com/shine1234/p/13356457.html

174求两个数的最大公约数

function countDivior(a,b) {      if(b===0) {           return a;     } else {          countDivior(b,a%b);     }}

175vue中的异步操作

async mounted () {	const data = await this.$axios.get("xxx");	this.list = data;}

72add(1)(2)(3)(4) == 10

function add (a) {	return function (b) {		return function (c) {			return function (d) {				return a + b + c + d			}		}	}}-----------柯里化function add (...args) {	return args.reduce((a, b) => a + b)//reduce里面可以放一个累加器(累加函数)进行累加效果}function currying (fn) {	let args = []	return function _c (...newArgs) {		if (newArgs.length) {			// 合并参数			args = [...args, ...newArgs];			return _c		} else {			return fn.apply(this, args)		}	}}//回调函数是一个函数作为另一个函数的参数,在另一个函数内部执行let addCurry = currying(add)// 注意调用方式的变化console.log(addCurry(1)(2)(3)(4, 5)())

3 [“1”,“2”,“3”].map(parseInt)结果

字符串1,2,3作为元素;0,1,2作为下标分别调用 parseInt 函数。即分别求出 parseInt(‘1’,0), parseInt(‘2’,1), parseInt(‘3’,2)的结果。第二个参数 区间范围介于2~36之间; 当参数为 0,parseInt() 会根据十进制来解析; 如果忽略该参数,默认的基数规则:如果 string 以 “0x” 开头,parseInt() 会把 string 的其余部分解析为十六进制的整数;parseInt(“0xf”) //15 …

[‘1’,‘2’,‘3’].map(parseInt)即

parseInt(‘1’,0);radix 为 0,parseInt() 会根据十进制来解析,所以结果为 1;

parseInt(‘2’,1);radix 为 1,超出区间范围,所以结果为 NaN;

parseInt(‘3’,2);radix 为 2,用2进制来解析,应以 0 和 1 开头,所以结果为 NaN。

19在前端使用js直接计算0.1+0.2的值时,得到的结果为0.30000000000000004,为什么,如何写代码才能避免该情况(请写出代码)?

由于二进制浮点数中0.1和0.2并不是十分精确

最简单的就是先把0.1和0.2换成别的数字(因为在js中只有这两个数相加有bug,例如:1.1+1.2不会有问题),所以先让0.1和0.2分别乘以10,求和之后再除以10 ,则不会有问题:(0.1*10+0.2*10)/10 ===0.3

或者parseFloat((0.1+0.2).toFixed(10)) ===0.3

求两个数对的和(整数或浮点数)
parseFloat((0.1+0.2).toFixed(10)) 
toFixed(10)规定了小数的位数,0到20之间

176 字符串前后空位的删除,tirm方法的实现

str.trim()  str.trimStart()   str.trimEnd()String.prototype.trim = function(){    return this.replace(/^(\s*)|(\s*)$/g, '');}

109 每隔一段时间执行一次函数,执行次数一定

function repeat (func, times, wait) {       return function (content){          var count = 0;          var interval = setInterval(function(){            count += 1;            func(content);            if(count === times){                clearInterval(interval);              }          }, wait);      }} const repeatFunc = repeat(alert, 4, 3000)repeatFunc("hellworld");

177css3不需要回流和重绘的属性:

  • transform
  • opacity
  • filter
  • Will-change

will-change属性可以提前通知浏览器我们要对元素做什么动画,这样浏览器可以提前准备合适的优化设置。这样可以避免对页面响应速度有重要影响的昂贵成本。元素可以更快的被改变,渲染的也更快,这样页面可以快速更新,表现的更加流畅。

will-change: transform, opacity;

179

实现函数 keys(o, level),能够获取指定层次的键。示例:let o = {  x: { a: 1, b: 2 },  y: 3,  z: {c: 1, d: 2, p: {m: 3}}}keys(o, 1) // 返回 ['x', ‘y’, ‘z']keys(o, 2) // 返回 ['a', ‘b’, ‘c’, ‘d’ ‘p']keys(o, 3) // 返回 [‘m’]keys(o, 4) // 返回 []
function keys (o, level) {
	if (level <= 1) {
		return Object.keys(object);
	}
	const accumulatedKeys = [];
	for (let value of Object.values(object)) {
		if (typeof value === 'object') {
			accumulatedKeys.push(...keys(value, level - 1));
		}
	}
	return accumulatedKeys;
}

180

const obj = {a: 2};
const a = 1;
console.log(obj > a);
大于运算符的操作数可以是任意类型,单只有数字和字符串才能真正执行比较操作,其他类型都需要转换
如果操作数是对象,先使用valueOf()转换为原始值,如果结果不是原始值,再使用toString()转换
在对象转换为原始值之后,如果至少有一个操作数不是字符串,则两个操作数都转换为数字进行比较
原始值指基础类型值
({a: 2}) > 1就相当于 NaN > 1,应该是 false

181reverse()是颠倒数组的方法

方法重载表示传入的参数不同

182金额转换为千分位

function formatNum(str) {
    var newStr = "";
    var count = 0;
    if(str.indexOf(".") === -1){
        for(var i=str.length-1;i>=0;i--){
            if(count % 3 == 0 && count != 0){
            	newStr = str.charAt(i) + "," + newStr;
        	}else{
        		newStr = str.charAt(i) + newStr;
    	}
    	count++;
        str = newStr + ".00"; //自动补小数点后两位
        console.log(str)
    } else {
    for(var i = str.indexOf(".")-1;i>=0;i--){
        if(count % 3 == 0 && count != 0){
        	newStr = str.charAt(i) + "," + newStr; //碰到3的倍数则加上“,”号
        }else{
        	newStr = str.charAt(i) + newStr; //逐个字符相接起来
        }
        count++;
    }
        str = newStr + str.substring(str.indexOf("."));
        console.log(str.toFixed(2));//保留两位小数
    }
}

183二维路径规划问题

给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。说明:每次只能向下或者向右移动一步。

输入:grid = [[1,3,1],[1,5,1],[4,2,1]]
输出:7
解释:因为路径 1→3→1→1→1 的总和最小。

解题思路
当前数的最小和 = 当前数 + min(左边数最小和,上边数最小和)
特例:第一列、第一行,需要单独处理

const minPathSum = grid => {    const row = grid.length,        col = grid[0].length;    for (let i = 1; i < row; i++) {        grid[i][0] += grid[i - 1][0];    }    for (let j = 1; j < col; j++) {        grid[0][j] += grid[0][j - 1];    }    for (let i = 1; i < row; i++) {        for (let j = 1; j < col; j++) {            grid[i][j] += Math.min(grid[i - 1][j], grid[i][j - 1]);        }    }    return grid[row - 1][col - 1];};

184实现set

const a = new MySet([1,2,3,3])
a.add(4)
a.remove(4)

class Set {	constructor() {		this.items = {};	}		add(value) {		if (!this.has(value)) {//注意			this.items[value] = value;			return true;		} else {			return false;		}	}	remove(value) {		if (this.has(value)) {			delete this.items[value];			return true;		} else {			return false;		}	}}

185

把一段字符串中数字相关的放在数组中输出,如果是数字直接使用数字类型,其他都使用字符串类型输入:const str = '这是一篇文章:加快递费3.22X10^5,就开始的经费3673降低开jvjsldfjXDJKFLD发洛索洛芬2/3,是杜绝浪费0.12345,晋升的了客服-2344'输出结果:['3.22X10^5',3673,'2/3',0.12345,-2344]function getNum (str) {    var arr = [];    var reg = /X|\^|\/|\.|\d|\-/;    	while (reg.exec(str)) {		var count = 0;		var j = 0;		for (var i = reg.exec(str) + 1; i < str.length; i++) {			if (reg.test(str[i])) {				count++;			} else {				arr[j] = str.splice(reg.exec(str), count);    			j++;			}		}	}    return arr;}match   [ , , , ,]

186 splice

splice(index,howmany,item1,.....,itemX)index使用负数可从数组结尾处规定位置,必填howmany要删除的项目数量,必填item1,.....,itemX 向数组添加的新项目,选填

187

动态作用域:函数内的成员是否可以被访问只有在运行的时候才能确定

function f(){	alert(x);}function f1(){	var x = 1;	f();}function f2(){	var x = 2;	f();}f1();//报错:x没有定义,说明JS没有动态作用域f2();

JS只有静态作用域lexical,也叫词法作用域或者闭包,在词法创建阶段就确定了相关的作用域。闭包:引用了自由变量的函数。

function f(){	var x = 100;	function g(){		...	}	g();}f();function f(){//f()创建的时候(浏览器解析的时候),给f添加一个看不到摸不着的成员[[scope]] 		  	 //f.[[scope]] == window			 //f()被调用的时候会创建自己的一个词法环境f.le, f.le ->f.[[scope]]//在预处理阶段(上一行解释,f()刚刚被调用时),f.le{x = undefined, g(){...}},g.[[scope]] == f.le//在预处理阶段,无论g()是函数声明还是函数表达式创建的都会把g()加入到f.le中	var x = 100;//在执行阶段,f.le{x = 100, g(){...}}	function g(){//在预处理阶段,g.[[scope]] == f.le		...	}	g();//g()在运行时,会创建自己的词法环境,g.le ->g.[[scope]]	//综上形成一条链条	//g.le -> g.[[scope]] == f.le -> f.[[scope]] == window}f();

112手写Promise.all和Promise.race

//Promise.allfunction promiseAll (promises) {	if (!Array.isArray(promises)) {		throw new Error ("promises must to be an array!!!");	}	return new Promise (function (resolve, reject) {		let promiseNum = promises.length;		let resolvedCount = 0;		let resolveValues = new Array(promiseNum);        for (let i = 0; i < promiseNum; i++) {            try{                promises[i].then(function (value) {                    resolveValues[i] = value;                    if (++resolvedCount === promiseNum) {                    	resolve(resolveValues);                    }                }            } catch (error) {            	reject(error);            }        }	})}//Promise.racefunction promiseRace(promise) {	if (!Array.isArray (promises)) {		throw new Error ("promises must be an array!!!");	}	let resolved = false;	return new Promise(function (resolve, reject) {		try{			promises.forEach(p =>                p.then(data => {                	if (!resolved) {                		resolved = true;                		resolve (data);                	}                })            )		} catch (error) {			reject(error);		}	})}

202下列代码存在几个变量没有被回收?

var i = 1;var i = 2;var add = function() {  var i = 0;  return function(){		i++;		console.log(i);	}}();add();

代码回收规则如下:( 3个)

1.全局变量不会被回收。

2.局部变量会被回收,也就是函数一旦运行完以后,函数内部的东西都会被销毁。

3.只要被另外一个作用域所引用就不会被回收

有3个变量没有被回收,首先是全局变量中的i,第二行声明被忽略,赋值会覆盖掉第一行,因此只有1个。第二个是var add,这个变量也没有回收,他定义了一个匿名函数,并将它赋给了add。第三个就是闭包中的变量i,闭包中的局部变量是不会被回收的,因此是3个变量没有被回收。

188

function addCounter() {    var counter = 0;    const myFunction = function() {        counter = counter + 1;        return counter;    }    return myFunction;}const increment = addCounter();const c1 = increment();const c2 = increment();const c3 = increment();console.log(c1, c2, c3);//1, 2, 3-------------------------function fn(a) {    console.log(a);    var a = 2;    function a() {    	console.log(a);    }}fn(1);//f a() { console.log(a) }//函数的声明大于变量-----------------function fn1() {	console.log(this);}fn1();//windowfn1.call({x: 100});//{x: 100}const fn2 = fn1.bind({x: 200});fn2();//{x: 200}------------当一个块级容器display:flex时,怎么设置使他的自己由顶部向下排列,再偏右排列flex-direction: column;justify-content: flex-start;align-items: flex-end;-------------------JavaScript中 window 对象的子对象不包含以下那个对象:documenthistoryselfmessage******--------------------------------------------------------------var string = 'string';var number = 0;var bool = true;console.log(number || string);//'string'console.log(number && string);//0console.log(bool || number);//trueconsole.log(bool && number);//0-----------------------------------------------function Foo() {	console.log(this.location);}Foo();//当前窗口的Location对象---------------------javascript中的数字在计算机内存储为多少Byte?JavaScript内部,所有数字都是以64位浮点数形式储存,即使整数也是如此8 Byte = 64bit

42如何渲染⼏万条数据并不卡住界⾯

// 优化性能,插⼊不会造成回流const fragment = document.createDocumentFragment();ul.appendChild(fragment);docunment.createElementdocument.documentElement

189

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。输入:nums = [-2,1,-3,4,-1,2,1,-5,4]输出:6解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。function maxNum(nums) {    var arr = [];    for (var i = 0; i < nums.length; i++) {        var maxValue = nums[i];        var tempValue = nums[i];        for (var j = i + 1; j < nums.length; j++) {            tempValue += nums[j];            if (tempValue > maxValue) {            	maxValue = tempValue;            }        }        arr[i] = maxValue;    }    return Math.max(...arr);}var nums = [-2,1,-3,4,-1,2,1,-5,4];console.log(maxNum(nums));

190

setState本身并不是异步,只是因为react的性能优化机制体现为异步。在react的生命周期函数或者作用域下为异步,在原生的环境下为同步。

setState 只在合成事件和钩子函数中是“异步”的,在原生事件和 setTimeout 中都是同步的。
合成事件:就是react 在组件中的onClick等都是属于它自定义的合成事件
原生事件:比如通过addeventListener添加的,dom中的原生事件

191

输入一个字符串,打印出该字符串中字符的所有排列。你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。示例:输入:s = "abc"输出:["abc","acb","bac","bca","cab","cba"]
我们将这个问题看作有 nn 个排列成一行的空位,我们需要从左往右依次填入题目给定的 nn 个字符,每个字符只能使用一次。首先可以想到穷举的算法,即从左往右每一个空位都依次尝试填入一个字符,看是否能填完这 nn 个空位,编程实现时,我们可以用「回溯法」来模拟这个过程。

定义递归函数 \texttt{backtrack}(i, \textit{perm})backtrack(i,perm) 表示当前排列为 \textit{perm}perm,下一个待填入的空位是第 ii 个空位(下标从 00 开始)。那么该递归函数分为两个情况:

如果 i=ni=n,说明我们已经填完了 nn 个空位,找到了一个可行的解,我们将 \textit{perm}perm 放入答案数组中,递归结束。

如果 i {
        if (i === n) {
            rec.push(perm.toString());
            return;
        }
        for (let j = 0; j < n; j++) {
            if (vis[j] || (j > 0 && !vis[j - 1] && arr[j - 1] === arr[j])) {
                continue;
            }
            vis[j] = true;
            perm.push(arr[j]);
            backtrack(arr, i + 1, n, perm);
            perm.pop();
            vis[j] = false;
        }
    }

    backtrack(arr, 0, n, perm);
    const size = rec.length;
    const recArr = new Array(size).fill(0);
    for (let i = 0; i < size; i++) {
        recArr[i] = rec[i].split(',').join('');
    }
    return recArr;
};

192

function primeNubmer(n){ for(var i=2 ; i

193js实现两个大整数相乘

一般涉及到大整数,都需要考虑通过数组或者字符串来模拟算术运算。我们通过数组来表示两个数字a、b(这里从左往右需要从个位数到最高位),这里的相乘只需要理解一点:a的每一位a[i]乘以b的每一位b[j],我们可以先将其放在结果中的result[i+j]中。这是模拟运算的过程。剩下的只需要将result中每一位大于9的进行进位即可。

function dazhenghsuAdd(str1,str2){
    str1=str1.split('').reverse();
    str2=str2.split('').reverse();
    let result=[];
    for(let i=0;i9){
            temp=Math.floor(result[k]/10);
            result[k]=result[k]%10;
            result[k+1]=result[k+1]||0;
            result[k+1]+=temp;
        }
    }
    return result.reverse().join('');
}

194Postman中post的数据类型

1、form-data 将表单的数据组织成Key-Value形式,也可以上传文件

2、x-www-form-urlencoded 将表单内的数据转换为Key-Value

3、raw 传输txt,json xml,html的数据

4、binary 只可以上传二进制数据,用来上传文件,一次只能上传1个数据

195

for in可遍历原型链上扩展的属性,Object.keys() 只遍历自身属性

sort会改变原数组

196BIGO

三个并排的div宽度设置为33.3%,会出现问题?

理想中是显示在一行中,事实却是两行。
原因是因为: col元素 display: inline-block后,元素后面的换行符以及空格都会被算上宽度,所以会溢出。
两种解决方法:

  1. .col加上float: left
  2. .container加上font-size: 0

line-height是干什么的?

line-height 行高,常见作用有二。

1.如果可能有换行,保证行与行之间距离合适。

2.居中。左侧字体14px,右侧字体18px。如果用一个行高将两部分框起来,可以保证左右两部分中心水平居中。


http1.0缓存弊端

HTTP/1.0缓存机制完全依赖时间,弊端显而易见,服务器、客户端的时钟不同步,文档的更新周期小于1s, 都会出现问题。

所以HTTP/1.1提倡的缓存机制是,对比文档的hash值,文档内容变,则hash变,用相对时间代替绝对时间

HTTP/1.1 继承 HTTP/1.0 所以HTTP/1.0的相关字段仍然有效,保留的这些字段就是为了兼容那些仅支持HTTP/1.0的客户端。 HTTP/1.1服务器不应该设置与1.0矛盾的过期策略, 1.1的服务器在没有文档hash值时,也可以使用If-Modified-Since进行判断文档过期。

新增字段:

  • Cache-Control: 用来控制浏览器的缓存行为
  • ETag: 文档的Hash值
  • If-None-Match: 用来验证资源是否过期,即文档Hash值是否变化

Cache-Control最容易理解也是最常用的就是:

  • no-cache: 浏览器缓存,但是认为是过期缓存
  • no-store: 浏览器不缓存
  • max-age:缓存有效时间段

https的加密原理

HTTPS 没有采用单一的技术去实现,而是根据他们的特点,充分的将这些技术整合进去,以达到性能与安全最大化。这套整合的技术称之为 SSL(安全套接层),因此 HTTPS 并非是一项新的协议,它只是在 HTTP 上披了一层加密的外壳。


如何知道http的传输已经结束

1.Content-Length

2.Transfer-Encoding

https://www.dazhuanlan.com/cloud_zhao/topics/1414445


WebSocket是哪一层

websocket和http一样都是传输层协议、都是基于tcp应用层协议

tcp属于哪⼀层(1** 物理层 -> 2 数据链路层 -> 3 ⽹络层(ip)-> 4 传输层(tcp) -> 5 应⽤层(http)


闭包的原理和使用场景


实现柯里化

把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

好处:参数确认、提前确认、延迟执行


es6代理


http为什么要用长连接,一般用在什么场景中

设置Connection为keep-alive就算是长连接了,但要服务器和客户端都设置

长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况;

而像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。

https://www.cnblogs.com/xifenglou/p/12888615.html


状态码 304 5xx


tcp连接过程中的状态考察

两端都为 CLOSED 状态

客户端便进⼊ SYN-SENT 状态

服务端进⼊ SYN-RECEIVED 状态

客户端进⼊ ESTABLISHED 状态


四次挥手,如果最后一个ack丢了会怎么样

1、当第四步的A发送的确认报文,B收到时,A会等待2MSL的时间后,连接彻底关闭。(因为B收到了,所以2MSL时间内B不会重发第三步的释放报文)

2、当第四步的A发送的确认报文,B没有收到时,B会继续发送第三步的释放报文,A收到后会继续发送第四步的确认报文(此时会重新启动2MSL计时器,重新等待2MSL时间),若在接下来的2MSL的时间内未收到B发送的第三步的释放报文,则意味着B已经收到了A的ack确认报文,连接彻底关闭


tcp三次握手详细过程

建⽴连接三次握⼿

在 TCP 协议中,主动发起请求的⼀端为客户端,被动连接的⼀端称为服务端。不管是客户端还是服务端, TCP 连接建⽴完后都能发送和接收数据,所以 TCP 也是⼀个全双⼯的协议。起初,两端都为 CLOSED 状态。在通信开始前,双⽅都会创建 TCB 。 服务器创建完TCB 后遍进⼊ LISTEN 状态,此时开始等待客户端发送数据

第⼀次握⼿

客户端向服务端发送连接请求报⽂段。该报⽂段中包含⾃身的数据通讯初始序号。请求发送后,客户端便进⼊ SYN-SENT 状态,x 表示客户端的数据通信初始序号。

第⼆次握⼿

服务端收到连接请求报⽂段后,如果同意连接,则会发送⼀个应答,该应答中也会包含⾃身的数据通讯初始序号,发送完成后便进⼊ SYN-RECEIVED 状态。

第三次握⼿

当客户端收到连接同意的应答后,还要向服务端发送⼀个确认报⽂。客户端发完这个报⽂段后便进⼊ ESTABLISHED 状态,服务端收到这个应答后也进⼊ESTABLISHED 状态,此时连接建⽴成功。

你是否有疑惑明明两次握⼿就可以建⽴起连接,为什么还需要第三次应答?

因为这是为了防⽌失效的连接请求报⽂段被服务端接收,从⽽产⽣错误

可以想象如下场景。客户端发送了⼀个连接请求 A,但是因为⽹络原因造成了超时,这时 TCP 会启动超时重传的机制再次发送⼀个连接请求 B。此时请求顺利到达服务端,服务端应答完就建⽴了请求。如果连接请求 A 在两端关闭后终于抵达了服务端,那么这时服务端会认为客户端⼜需要建⽴ TCP 连接,从⽽应答了该请求并进⼊ ESTABLISHED 状态。此时客户端其实是 CLOSED 状态,那么就会导致服务端⼀直等待,造成资源的浪费


insigned int 类型扩展长度

int 数据,内存就分配给它两个字节


https的建立连接过程

客户端发起https连接

服务端发送证书

客户端验证服务端发来的证书验证证书生成随机数、此随机数就是后面用的对称加密的私钥生成握手信息

服务端接收随机数加密的信息,并解密得到随机数,验证握手信息是否被篡改

客户端验证服务端发送回来的握手信息,完成握手


一个长度为一百万的数组中,有超过一半的数都是某一个值,求这个值

1.定义一个辅助数组 zero ,里面全是0;

2.循环输入的数组 arr ,将 arr 每个位置的值(arr[i])对应到辅助数组zero里的每个位置,使之++。

即 如果arr[1]的值是2,就对应到zero[2],使zero[2]的值++;……;如果arr[5]的值又是2,就再对应到zero[2],使zero[2]的值++;

3.循环辅助数组 zero,将其中的数与 arr长度的一半作比较,如果大于则输出该数的位置。即如果 arr.length/2 == 3,zero[3] == 4,则输出3。

function arrCount(arr){	var count = arr.length/2;	var zero = new Array(Math.floor(count);	var res = 0;	if (arr.length == 0) {		console.log("This arr is null!");		return;	}	for(let i = 0; i < arr.length; i++){		zero[arr[i]]++;		if (zero[arr[i]] >= count) {		return arr[i];		}	}}

197前序顺序是(根节点排最先,然后同级先左后右);中序顺序是(先左后根最后右);后序顺序是(先左后右最后根)。


1设置元素浮动后,该元素的display值是(block)

2document load 与document ready的区别

页面加载完成有两种事件

load是当页面所有资源全部加载完成后(包括DOM文档树,css文件,js文件,图片资源等)执行一个函数

问题:如果图片资源较多,加载时间较长,onload后等待执行的函数需要等待较长时间,所以一些效果可能受到影响

$(document).ready()是当DOM文档树加载完成后执行一个函数 (不包含图片,css等)所以会比load较快执行

在原生的js中不包括ready()这个方法,只有load方法就是onload事件

13LocalStorage用于浏览器保存持久数据接口,已有保存数据接口setItem(key, value)和获取数据接口getItem(key)。因项目需要我们需要为这个localStorage的数据保存添加一个有效时间time(单位:秒),满足在有效时间内,key-value有效,超过有效时间 即time秒后失效。我们把这个改装后台的localStorage命名为Xstorage,请根据已有的接口,来实现函数.setItem(key, value, time)和.getItem(key)的方法。

20flex-grow默认值是0;弹性布局中,子元素的float、clear、vertical-align属性无效;弹性布局的定义是取决于容器元素的display属性等于flex或inline-flex来决定的

24请使用ES5和ESNext分别实现一种继承

(ESNext:ES6转JavaScript)

***28js请使用正则表达式实现匹配网址(从http://www.xxx.com/?a=1中www.xxx.com,协议头包含http/https/ftp

31请实现对数组[{a:2},{a:1},{a:0},{a:10},{a:2.1}]按属性a为浮点数的基准进行过滤,过滤掉其中属性a为浮点数的项

array.filter((item, index) => {}

37,假如base-input是你封装的组件,在内部如何接收外部传进去的lovingVue,以及内部如何更新外部lovingVue的值?;介绍一下组件中父子间通讯?(https://blog.csdn.net/bigbear00007/article/details/104887792);如何解决跨域问题?

38根据以下xml请写出对应的json

12张三13李四

答案:

var list = [{“id”:“12”,“name”:“张三”},{“id”:“13”,“name”:“李四”}];

47Vue中给data中的对象属性添加一个新的属性时会发生什么,如何解决?($set())

https://blog.csdn.net/weixin_45259626/article/details/106078006

49写一段代码,使用vue实现组件内部双向数据绑定,例如有一个输入框组件,用户输入时,同步父组件页面的内容

https://www.cnblogs.com/mahmud/p/10492189.html

https://blog.csdn.net/qq_27852041/article/details/87855130

61模块化CSS的方法,Native CSS/LESS/SCSS不同的实现,优势和问题(CSS模块化的命名问题、权重问题、变量问题)

CSS 模块化的实现方式

BEM 命名规范

BEM 的意思就是块(block)、元素(element)、修饰符(modifier)。是由 Yandex 团队提出的一种前端命名方法论。这种巧妙的命名方法让你的 css 类对其他开发者来说更加透明而且更有意义。

scss,@import ‘./css/base.css’;/页面基础样式/

less支持了模块化,可以@import ‘xxx.less’的形式导入其他less文件实现模块化。

css也可以用@import ‘xxx.css’方式实现模块化,所有页面只引用一个style.css。

这样可以http请求的消耗,同样方便合作开发,后期新增和删除模块只需修改这一个文件即可。

63不直接用±/,实现字符串数组的add(strA, strB)

//加减乘除//加法function accAdd(arg1,arg2){         var r1,r2,m;         try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0};         try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0};         m=Math.pow(10,Math.max(r1,r2));         return (arg1*m+arg2*m)/m;}//减法function accSubtr(arg1,arg2){        var r1,r2,m,n;        try{r1=arg1.toString().split(".")[1].length;}catch(e){r1=0;}        try{r2=arg2.toString().split(".")[1].length;}catch(e){r2=0;}        m=Math.pow(10,Math.max(r1,r2));        //动态控制精度长度        n=(r1>=r2)?r1:r2;        return ((arg1*m-arg2*m)/m).toFixed(n);} //乘法function accMul(arg1,arg2){        var m=0,s1=arg1.toString(),s2=arg2.toString();          try{m+=s1.split(".")[1].length}catch(e){};          try{m+=s2.split(".")[1].length}catch(e){};          return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m);}//除法function accDivCoupon(arg1,arg2){        var t1=0,t2=0,r1,r2;        try{t1=arg1.toString().split(".")[1].length;}catch(e){}        try{t2=arg2.toString().split(".")[1].length;}catch(e){}        with(Math){            r1=Number(arg1.toString().replace(".",""));            r2=Number(arg2.toString().replace(".",""));            return (r1/r2)*pow(10,t2-t1);        }}

66手写实现一个基本功能的promise

function Promise(exector) {        let self = this;        //status表示一种状态        let status = "pending";        let value = undefined;        let reason = undefined;        //成功执行        function resolve(value) {                if (status == 'pending') {                        self.value = value;                        self.status = "resolve";                }    	}        //执行失败        function reject(reason) {                if (status == 'pending') {                        self.reason = reason;                        self.status = "reject"                }        }        //对异常操作        try {    	    	exector(resolve, reject)        } catch (e) {    	    	reject(e)    	}    	//设置promise的then方法        Promise.prototype.then = function(reject, resolve) {                let self = this;                if (self.status == 'resolve') {        	        	reject(self.value)                }                if (self.status == 'reject') {        	        	resolve(self.reason)                }        }        //new 一个promise  进行测试          let promise = new Promise((reject, resolve) => {    	        resolve("return resolve");        });        promise.then(data => {    	        console.log(`success${data}`);        }, err => {    	        console.log(`err${err}`);		})}

68实现一个具备基础功能的事件监听器,addEventListener dispatchEvent removeEventListener

69编程题:输出旋转数组的最小元素

//直接遍历,找到最小值。像选择排序一样,找到最小值索引,找到最小值//利用二分查找。如果中间元素值>最后一个元素值,说明最小值右半区间,如果中间元素<最后一个元素区间,说明最小值在左半区间,如果相等说明有相同元素,需要将判断区间往前缩一下,继续判断,不断循环,当二分查找的的左右区间相等了,就说明找到最小值了。function minNumberINRotateArray (rotateArray) {	var len = rotateArray.length;	if (len = 0) {return 0;}	var left = 0;	var right = len - 1;	while (left < right) {		var mid = Math.floor(len / 2);		if (rotateArray[mid] > rotateArray[right])            {                left = mid + 1;            }else if (rotateArray[mid] < rotateArray[right]) {                right=mid;            }else {            	right=right-1;            }        }	}	return rotateArray[left];}

***70编程题:给定数组arr,设数组长度为n,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim,代表要找的钱数,求换钱的方法数有多少种。由于方法的种数比较大,所以要求输出对109+710^9+7109+7进行取模后的答案。(动态规划的题,老难了)

73将字符串中的rgb颜色转换为16进制

function formatColor(str) {    const newstr = str.replace(/(rgb\()|(\))/g, '')    const arr = newstr.split(',')    let res = '#'    for(var val of arr){        res += fillZero(switchNumToSixteen(parseInt(val)))    }    return res} function switchNumToSixteen(num) {    return num.toString(16)//转换为16进制}  function fillZero(str) {    if(parseInt(str, 16) < 16) {//转换为16进制        return '0' + str    }    return str}

74根据包名,在指定空间中创建对象

输入描述:
namespace({a: {test: 1, b: 2}}, 'a.b.c.d')
输出描述:
{a: {test: 1, b: {c: {d: {}}}}}
理解题意
命名空间
命名空间是一种代码封装技术,代码中的每个成员,都是自己的活动空间,彼此互不干扰。
首先理解题意,namespace($1, $2)函数中第一个参数是现有命名空间中的对象,而第二个参数是需要此空间实现的结构(即对象的包含关系),可知是a包含b包含c包含d;
解题思路
首先因为题目所要求创建的空间是顺序的,所以直接通过循环,将其一个个创建即可。
当空间中包含对象时(如a:{test:1})则保留此对象;当包含内容不是对象时(如b:2),则将其设置为一个空对象。如果不包含此空间名,则在其上一级空间中创建一个空对象。
function namespace(oNamespace, sPackage) {
    var package = sPackage.split('.');
    var obj = oNamespace;    
    for (var i = 0; i < package.length; ++i) {
        if (typeof obj[package[i]] !== 'object') {
            obj[package[i]] = {};
        } 
        obj = obj[package[i]];
    }
    return oNamespace;
}

76有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。

省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。

给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。

返回矩阵中 省份 的数量。

思路:

利用路径标记的方式,采用一维数组标记是否相连:若城市 i 与城市 j 相连,则与城市 j 相连的其它城市均与城市 i 相连。

通过dfs方式可以搜索全部的相连城市,并根据搜索的路径确定当前城市是否为当前类别。

89断开链接四次握⼿

TCP 是全双⼯的,在断开连接时两端都需要发送 FIN 和 ACK 。

第⼀次握⼿

若客户端 A 认为数据发送完成,则它需要向服务端 B 发送连接释放请求。

第⼆次握⼿

B 收到连接释放请求后,会告诉应⽤层要释放 TCP 链接。然后会发送 ACK包,并进⼊ CLOSE_WAIT 状态,表示 A 到 B 的连接已经释放,不接收 A 发的数据了。但是因为 TCP 连接时双向的,所以 B 仍旧可以发送数据给 A。

第三次握⼿

如果此时还有没发完的数据会继续发送,完毕后会向 A 发送连接释放请求,然后 B 便进⼊ LAST-ACK 状态。PS:通过延迟确认的技术(通常有时间限制,否则对⽅会误认为需要重传),可以将第⼆次和第三次握⼿合并,延迟 ACK 包的发送。

第四次握⼿

A 收到释放请求后,向 B 发送确认应答,此时 A 进⼊ TIME-WAIT 状态。该状态会持续2MSL(最⼤段⽣存期,指报⽂段在⽹络中⽣存的时间,超时会被抛弃) 时间,若该时间段内没有 B 的重发请求的话,就进⼊ CLOSED 状态。当 B 收到确认应答后,也便进⼊CLOSED 状态。

94表单可以跨域吗 可以

Form表单可以跨域是因为要保持兼容性,当请求到另一个域名后,原页面得脚本无法获取新页面中得内容,提交的form表单数据不需要返回,所以浏览器认为是安全得行为,所以浏览器不会阻止form表单跨域,而ajax我们需要返回的数据,浏览器认为不安全,所以会阻止这个请求行为。

98 监听input的哪个事件,在什么时候触发

onfocus onblur onkeydown onkeyup onclick

onchange 当input失去焦点并且它的value值发生变化时触发

onselect 当input里的内容文本被选中后执行一段,只要选择了就会触发,不是非得全部选中

oninput 当input的value值发生变化时就会触发,不用等到失去焦点(与onchange的区别)

100mixin 和 mixins 区别

mixin ⽤于全局混⼊,会影响到每个组件实例,通常插件都是这样做初始化的,虽然⽂档不建议我们在应⽤中直接使⽤ mixin ,但是如果不滥⽤的话也是很有帮助的,⽐如可以全局混⼊封装好的 ajax 或者⼀些⼯具函数等等。

mixins 应该是我们最常使⽤的扩展组件的⽅式了。如果多个组件中有相同的业务逻辑,就可以将这些逻辑剥离出来,通过 mixins 混⼊代码,⽐如上拉下拉加载数据这种逻辑等等。

另外需要注意的是 mixins 混⼊的钩⼦函数会先于组件内的钩⼦函数执⾏,并且在遇到同名选项的时候也会有选择性的进⾏合并。

101工厂模式

当然⼯⼚模式并不仅仅是⽤来 new 出实例。

可以想象⼀个场景。假设有⼀份很复杂的代码需要⽤户去调⽤,但是⽤户并不关⼼这些复杂的代码,只需要你提供给我⼀个接⼝去调⽤,⽤户只负责传递需要的参数,⾄于这些参数怎么使⽤,内部有什么逻辑是不关⼼的,只需要你最后返回我⼀个实例。这个构造过程就是⼯⼚。

⼯⼚起到的作⽤就是隐藏了创建实例的复杂度,只需要提供⼀个接⼝,简单清晰。

在 Vue 源码中,你也可以看到⼯⼚模式的使⽤,⽐如创建异步组件

125编写一个函数repeatStr(),使用字符串的repeat()方法来将任意一个字符串进行不断重复,然后超过20个字符的部分就截断舍弃,也就是最终返回一个包含20个字符的字符串。

function repeatStr(str) {
  const len = 20;
  const n = Math.ceil(len / str.length);
  return str.repeat(n).substr(0, len);
}

126编写一个函数shieldStr(),用于接收一个电子邮件地址,然后将@前面所有的字符屏蔽掉。比如,[email protected]将被屏蔽为:**********@foxmail.com。

function shieldStr(str) {
  const arr = str.split("@");
  const str1 = "*".repeat(arr[0].length);
  const str2 = arr[1];
  return `${str1}@${str2}`;
}

127

在实际开发中,为什么我们要把“类数组”转换为“真正的数组”,其目的是什么?

主要是为了使得类数组也能使用真正数组的各种方法,比如push()、slice()等。

128

const person = {    name: "Jack",    age: 24};const result = Object.assign({}, person);result.name = "Lucy";console.log(result.name);console.log(person.name);//下面有一段代码,其运行结果是://"Lucy", "Jack"const person = {    name: {        first: "Jack",        last: "Mo"    },    age: 24};const result = Object.assign({}, person);result.name.first = "Lucy";console.log(result.name.first);console.log(person.name.first);//"Lucy", "Lucy"

135二叉树深度

//递归。树的深度=左子树的深度和右子树深度中最大者+1function TreeDepth(pRoot){    if(pRoot === null) return 0;    var left = TreeDepth(pRoot.left);    var right = TreeDepth(pRoot.right);    return Math.max(left,right)+1;}

136如何判断一个对象是 Map或者Set数据结构

//1. 可以通过 instanceofvar set = new Set();console.log(set instanceof Set);//2. 构造函数  constructorconsole.log(set.constructor == Set);//3. Object.prototype.toString.call()var set = new Set();console.log(Object.prototype.toString.call(set) == "[object Set]");//4. isPrototypeOfvar set = new Set();console.log(Set.prototype.isPrototypeOf(set));

139 对象a, b 存在相同的key值,b覆盖a属性值,如果a,b相同的key对应的值均为对象,则再次进行对象合并

143给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

//输入:nums = [-1,0,1,2,-1,-4]//输出:[[-1,-1,2],[-1,0,1]]


1 前端需要注意哪些SEO

1 合理的 title 、 description 、 keywords 。

语义化代码让搜索引擎容易理解⽹⻚,重要内容 HTML 代码放在最前:搜索引擎抓取 HTML 顺序是从上到下,有的搜索引擎对抓取⻓度有限制,保证重要内容⼀定会被抓取重要内容不要⽤ js 输出:爬⾍不会执⾏js获取内容

3 少⽤ iframe 。搜索引擎不会抓取 iframe 中的内容
4 ⾮装饰性图⽚必须加 alt。
5 提⾼⽹站速度。⽹站速度是搜索引擎排序的⼀个重要指标

2 HTML5 的离线储存怎么使⽤,⼯作原理能不能解释⼀下?

在⽤户没有与因特⽹连接时,可以正常访问站点或应⽤,在⽤户与因特⽹连接时,更新⽤户机器上的缓存⽂件
原理: HTML5 的离线存储是基于⼀个新建的 .appcache ⽂件的缓存机制(不是存储技术),通过这个⽂件上的解析清单离线存储资源,这些资源就会像 cookie ⼀样被存储了下来。之后当⽹络在处于离线状态下时,浏览器会通过被离线存储的数据进⾏⻚⾯展示
如何使⽤:
⻚⾯头部像下⾯⼀样加⼊⼀个 manifest 的属性;在 cache.manifest ⽂件的编写离线存储的资源;在离线状态时,操作 window.applicationCache 进⾏需求实现

在线的情况下,浏览器发现 html 头部有 manifest 属性,它会请求 manifest ⽂件,如果是第⼀次访问 app ,那么浏览器就会根据manifest⽂件的内容下载相应的资源并且进⾏离线存储。如果已经访问过 app 并且资源已经离线存储了,那么浏览器就会使⽤离线的资源加载⻚⾯,然后浏览器会对⽐新的 manifest ⽂件与旧的 manifest ⽂件,如果⽂件没有发⽣改变,就不做任何操作,如果⽂件改变了,那么就会重新下载⽂件中的资源并进⾏离线存储。

离线的情况下,浏览器就直接使⽤离线存储的资源。

4 HTML全局属性(global attribute)有哪些

class :为元素设置类标识
data-* : 为元素增加⾃定义属性
draggable : 设置元素是否可拖拽
id : 元素 id ,⽂档内唯⼀
lang : 元素内容的的语⾔
style : ⾏内 css 样式
title : 元素相关的建议信息

5 HTML5 为什么只需要写

HTML5 不基于 SGML ,因此不需要对 DTD 进⾏引⽤,但是需要 doctype 来规范浏览器的⾏为
⽽ HTML4.01 基于 SGML ,所以需要对 DTD 进⾏引⽤,才能告知浏览器⽂档所使⽤的⽂档类型

6 如何在⻚⾯上实现⼀个圆形的可点击区域?

svg
border-radius

7 viewport里的配置,延伸提问,怎样处理移动端1px被渲染成2px问题

局部处理
mate 标签中的 viewport 属性 , initial-scale 设置为 1
rem 按照设计稿标准⾛,外加利⽤ transfrome 的 scale(0.5) 缩⼩⼀倍即可;

全局处理
mate 标签中的 viewport 属性 , initial-scale 设置为 0.5
rem 按照设计稿标准⾛即可

8 div+css的布局较table布局有什么优点?

改版的时候更⽅便,只要改 css ⽂件。
⻚⾯加载速度更快、结构化清晰、⻚⾯显示简洁。
表现与结构相分离。
易于优化( seo )搜索引擎更友好,排名更容易靠前。

10 web开发中会话跟踪的⽅法有哪些

HTTP协议由两部分程序实现:一个客户端程序和一个服务器程序,它们运行在不同的端系统当中,通过交换HTTP报文进行会话。

在一个会话中,跟踪请求之间的数据成为会话跟踪。

(一)应用隐藏域进行会话跟踪(隐藏 input)
利用HTML中的隐藏域,在网页表单内填写客户端的信息。这些信息会随客户端的请求信息一起传送给服务器,服务器通过获取的这些信息来进行会话跟踪。
隐藏域的HTML标签如下:


应用隐藏域的请求信息在浏览器页面是看不到的,但是查看源代码的话是可以看到客户端的请求信息的,所以这种方式显然是不安全的,会导致信息泄露。
(二)SSL会话(Secure Socket Layer)
安全套接字(Secure Socket Layer,SSL)协议是Web浏览器与Web服务器之间安全交换信息的协议,提供两个基本的安全服务:鉴别与保密。在SSL中会使用密钥交换算法交换密钥;使用密钥对数据进行加密;使用散列算法对数据的完整性进行验证,使用数字证书证明自己的身份。
(三)Cookies
Cookie是由服务器端生成,发送给浏览器,浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。Cookie名称和值可以由服务器端开发自己定义,这样服务器可以知道该用户是否合法用户以及是否需要重新登录等。
服务器可以利用Cookies包含信息的任意性来筛选并经常性维护这些信息,以判断在HTTP传输中的状态。Cookies最典型的应用是判定注册用户是否已经登录网站,用户可能会得到提示,是否在下一次进入此网站时保留用户信息以便简化登录手续,这样就实现了对客户的追踪。
(四)URL重写
URL重写就是首先获得一个进入的URL请求然后把它重新写成网站可以处理的另一个URL的过程。举个例子来说,如果通过浏览器进来的URL是“UserProfile.aspx?ID=1”那么它可以被重写成 “UserProfile/1.aspx”,这样的URL,这样的网址可以更好的被网站所阅读。
如果浏览器不支持Cookie或用户阻止了所有Cookie,可以把会话ID附加在HTML页面中所有的URL上,这些页面作为响应发送给客户。这样,当用户单击URL时,会话ID被自动作为请求行的一部分而不是作为头行发送回服务器。这种方法称为URL重写。

(五)ip 地址

11 link 与 @import 的区别

link属于html标签。@import在css中使用表示导入外部样式表;
页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载;
import只在IE5以上才能识别,而link是HTML标签,无兼容问题;
link方式的样式的权重高于@import的权重;
link 支持使用javascript改变样式 (document.styleSheets),后者不可

总体来说: link 优于 @import

什么是FOUC?如何避免

Flash Of Unstyled Content :⽤户定义样式表加载之前浏览器使⽤默认样式显示⽂档,⽤户样式加载渲染之后再从新显示⽂档,造成⻚⾯闪烁。
解决⽅法:把样式表放到⽂档的

13 在⽹⻚中的应该使⽤奇数还是偶数的字体?为什么呢?

偶数字号相对更容易和 web 设计的其他部分构成⽐例关系

16 stylus/sass/less区别

均具有“变量”、“混合”、“嵌套”、“继承”、“颜⾊混合”五⼤基本特性;
Scss 和 LESS 语法较为严谨, LESS 要求⼀定要使⽤⼤括号“{}”, Scss 和 Stylus 可以通过缩进表示层次与嵌套关系
Scss ⽆全局变量的概念, LESS 和 Stylus 有类似于其它语⾔的作⽤域概念
Sass 是基于 Ruby 语⾔的,⽽ LESS 和 Stylus 可以基于 NodeJS NPM 下载相应库后进⾏编译;

17 postcss的作⽤

可以直观的理解为:它就是⼀个平台。PostCSS 提供了⼀个解析器,它能够将 CSS 解析成抽象语法树
通过在 PostCSS 这个平台上,我们能够开发⼀些插件,来处理我们的 CSS ,⽐如热⻔的: autoprefixer
postcss 可以对sass处理过后的 css 再处理 最常⻅的就是 autoprefixer

18 伪类和伪元素的区别

伪类表状态;伪元素是真的有元素
前者单冒号,后者双冒号

19请⽤CSS写⼀个简单的幻灯⽚效果⻚⾯

知道是要⽤ CSS3 。使⽤ animation 动画实现⼀个简单的幻灯⽚效果

.ani{ width:480px; height:320px; margin:50px auto; overflow: hidden; box-shadow:0 0 5px rgba(0,0,0,1); background-size: cover; background-position: center; -webkit-animation-name: "loops"; -webkit-animation-duration: 20s; -webkit-animation-iteration-count: infinite;}@-webkit-keyframes "loops" { 0% { background:url(http:// } 25% { background:url(http:// } 50% { background:url(http:// } 75% { background:url(http:// } 100% { background:url(http:// }}

21 如何使⽤CSS实现硬件加速?

硬件加速是指通过创建独⽴的复合图层,让GPU来渲染这个图层,从⽽提⾼性能,⼀般触发硬件加速的 CSS 属性有 transform 、 opacity 、 filter ,为了避免2D动画,在开始和结束的时候的 repaint 操作,⼀般使⽤tranform:translateZ(0)

22 如何实现⼩于12px的字体效果

transform:scale() 这个属性只可以缩放可以定义宽⾼的元素,⽽⾏内元素是没有宽⾼的,我们可以加上⼀个 display:inline-block ;

25 XML和JSON的区别?

JSON 相对 于XML 来讲,数据的体积⼩,传递的速度更快些。
JSON 与 JavaScript 的交互更加⽅便,更容易解析处理,更好的数据交互
JSON 对数据的描述性⽐ XML 较差
JSON 的速度要远远快于 XML

30 offsetWidth/offsetHeight,clientWidth/clientHeight与scrollWidth/scrollHeight的区别

offsetWidth/offsetHeight 返回值包含content + padding + border,效果与e.getBoundingClientRect()相同
clientWidth/clientHeight 返回值只包含content + padding,如果有滚动条,也不包含滚动条
scrollWidth/scrollHeight 返回值包含content + padding + 溢出内容的尺⼨

ele.scrollTop = 被卷去的上侧距离
ele.scrollHeight = 自身实际的高度(不包括边框)

31 Node的应⽤场景

特点:
它是⼀个 Javascript 运⾏环境
依赖于 Chrome V8 引擎进⾏代码解释
事件驱动
⾮阻塞 I/O
单进程,单线程
优点:
⾼并发(最重要的优点)
缺点:
只⽀持单核 CPU ,不能充分利⽤ CPU
可靠性低,⼀旦代码某个环节崩溃,整个系统都崩溃

32 eval是做什么的

它的功能是把对应的字符串解析成 JS 代码并运⾏应该避免使⽤ eval ,不安全,⾮常耗性能( 2 次,⼀次解析成 js 语句,⼀次执⾏)

由 JSON 字符串转换为JSON对象的时候可以⽤ eval

var obj =eval(’(’+ str +’)’);
var obj = str.parseJSON();
var obj = JSON.parse(str);

JSON 对象转换为JSON字符串

var last=obj.toJSONString();
var last=JSON.stringify(obj);

33 同步和异步的区别

同步:浏览器访问服务器请求,⽤户看得到⻚⾯刷新,重新发请求,等请求完,⻚⾯刷新,新内容出现,⽤户看到新内容,进⾏下⼀步操作
异步:浏览器访问服务器请求,⽤户正常操作,浏览器后端进⾏请求。等请求完,⻚⾯不刷新,新内容也会出现,⽤户看到新内容

34 说说严格模式的限制

变量必须声明后再使⽤
函数的参数不能有同名属性,否则报错
不能使⽤ with 语句
禁⽌ this 指向全局对象

35 什么是⾯向对象编程及⾯向过程编程,它们的异同和优缺点

⾯向过程就是分析出解决问题所需要的步骤,然后⽤函数把这些步骤⼀步⼀步实现,使⽤的时候⼀个⼀个依次调⽤就可以了
⾯向对象是把构成问题事务分解成各个对象,建⽴对象的⽬的不是为了完成⼀个步骤,⽽是为了描叙某个事物在整个解决问题的步骤中的⾏为
⾯向对象是以功能来划分问题,⽽不是步骤

37 谈⼀谈箭头函数与普通函数的区别?

函数体内的 this 对象,就是定义时所在的对象,⽽不是使⽤时所在的对象
不可以当作构造函数,也就是说,不可以使⽤ new 命令,否则会抛出⼀个错误
不可以使⽤ arguments 对象,该对象在函数体内不存在。如果要⽤,可以⽤ Rest 参数代替
不可以使⽤ yield 命令,因此箭头函数不能⽤作 Generator 函数

38JS动画与CSS动画区别及相应实现

CSS3 的动画的优点:
在性能上会稍微好⼀些,浏览器会对 CSS3 的动画做⼀些优化
代码相对简单
缺点:
在动画控制上不够灵活
兼容性不好
JavaScript 的动画正好弥补了这两个缺点,控制能⼒很强,可以单帧的控制、变换,同时写得好完全可以兼容 IE6 ,并且功能强⼤。对于⼀些复杂控制的动画,使⽤javascript 会⽐较靠谱。⽽在实现⼀些⼩的交互动效的时候,就多考虑考虑 CSS 吧

39 gulp是什么

gulp 是前端开发过程中⼀种基于流的代码构建⼯具,是⾃动化项⽬的构建利器;它不仅能对⽹站资源进⾏优化,⽽且在开发过程中很多重复的任务能够使⽤正确的⼯具⾃动完成
Gulp的特点:
易于使⽤:通过代码优于配置的策略,gulp 让简单的任务简单,复杂的任务可管理
构建快速: 利⽤ Node.js 流的威⼒,你可以快速构建项⽬并减少频繁的 IO 操作
易于学习

41快速的让⼀个数组乱序

var arr = [1,2,3,4,5,6,7,8,9,10];arr.sort(function(){ return Math.random() - 0.5;})console.log(arr);

43希望获取到⻚⾯中所有的checkbox怎么做

var domList = document.getElementsByTagName(‘input’)var checkBoxList = [];var len = domList.length; //缓存到局部变量while (len--) { //使⽤while的效率会⽐for循环更⾼    if (domList[len].type == ‘checkbox’) {    	checkBoxList.push(domList[len]);    }}

44Javascript中callee和caller的作⽤?

caller 是返回⼀个对函数的引⽤,该函数调⽤了当前函数;
callee 是返回正在被执⾏的 function 函数,也就是所指定的 function 对象的正⽂

45 addEventListener()和attachEvent()的区别

addEventListener() 是符合W3C规范的标准⽅法; attachEvent() 是IE低版本的⾮标准⽅法
addEventListener() ⽀持事件冒泡和事件捕获; ⽽ attachEvent() 只⽀持事件冒泡
addEventListener() 的第⼀个参数中,事件类型不需要添加 on ; attachEvent() 需要添加 ‘on’
如果为同⼀个元素绑定多个事件, addEventListener() 会按照事件绑定的顺序依次执⾏,attachEvent() 会按照事件绑定的顺序倒序执⾏

47 Javascript全局函数和全局变量

全局变量
Infinity 代表正的⽆穷⼤的数值。
NaN 指示某个值是不是数字值。
undefined 指示未定义的值。
全局函数

个人记忆方法:6(编码相关)+ 2(数据处理)+ 4(数字相关)+ 1(特殊)

编码相关:

escape()、unescape()、encodeURI()、decodeURI()、

encodeURIComponent()、decodeURIComponent()

数据处理:

Number()、String()

数字相关:

isFinite()、isNaN()、parseFloat()、parseInt()

特殊:

eval()

48怎么判断两个对象相等?

JSON.stringify(obj)==JSON.stringify(obj2);//true

50 深浅拷⻉

浅拷⻉
Object.assign 或者 展开运算符
深拷⻉
可以通过 JSON.parse(JSON.stringify(object)) 来解决,该⽅法也是有局限性的,会忽略 undefined

但是该⽅法也是有局限性的:
会忽略 undefined
会忽略 symbol
不能序列化函数
不能解决循环引⽤的对象

51 防抖/节流

防抖动是将多次执⾏变为最后⼀次执⾏,节流是将多次执⾏变成每隔⼀段时间执⾏

52变量提升

在⽣成执⾏环境时,会有两个阶段。第⼀个阶段是创建的阶段,JS 解释器会找出需要提升的变量和函数,并且给他们提前在内存中开辟好空间,函数的话会将整个函数存⼊内存中,变量只声明并且赋值为 undefined ,所以在第⼆个阶段,也就是代码执⾏阶段,我们可以直接提前使⽤在提升的过程中,相同的函数会覆盖上⼀个函数,并且函数优先于变量提升

53请简单实现双向数据绑定 mvvm

63编写⼀个⽅法 求⼀个字符串的字节⻓度,假设:⼀个英⽂字符占⽤⼀个字节,⼀个中⽂字符占⽤两个字节

function GetBytes(str){
    var len = str.length;
    var bytes = len;
    for(var i=0; i 255) bytes++;
    }
    return bytes;
}

64bind的⽤法,以及如何实现bind的函数和需要注意的点

bind 的作⽤与 call 和 apply 相同,区别是 call 和 apply 是⽴即调⽤函数,⽽bind 是返回了⼀个函数,需要调⽤的时候再执⾏。 ⼀个简单的 bind 函数实现如下

Function.prototype.bind = function(ctx) {
    var fn = this;
    return function() {
    	fn.apply(ctx, arguments);
    };
};

67 定义⼀个log⽅法,让它可以代理console.log的⽅法

//可⾏的⽅法⼀:
function log(msg) {
	console.log(msg);
}
log("hello world!") // hello world!
//如果要传⼊多个参数呢?显然上⾯的⽅法不能满⾜要求,所以更好的⽅法是:
function log(){
	console.log.apply(console, arguments);
}

70写⼀个 function ,清除字符串前后的空格

使⽤⾃带接trim() ,考虑兼容性:

if (!String.prototype.trim) {    String.prototype.trim = function() {    	return this.replace(/^\s+/, "").replace(/\s+$/,"");    }}var str = " \t\n test string ".trim();alert(str == "test string"); // alerts "true"

71实现每隔⼀秒钟输出1,2,3…数字

for(var i=0;i<10;i++){    (function(j){        setTimeout(function(){        	console.log(i+1)        },i*1000)    })(i)}

72实现⼀个函数,判断输⼊是不是回⽂字符串

function run(input) {    if (typeof input !== 'string') return false;    return input.split('').reverse().join('') === input;}

74负载均衡

多台服务器共同协作,不让其中某⼀台或⼏台超额⼯作,发挥服务器的最⼤作⽤
http 重定向负载均衡:调度者根据策略选择服务器以302响应请求,缺点只有第⼀次有效果,后续操作维持在该服务器 dns负载均衡:解析域名时,访问多个 ip 服务器中的⼀个(可监控性较弱)
反向代理负载均衡:访问统⼀的服务器,由服务器进⾏调度访问实际的某个服务器,对统⼀的服务器要求⼤,性能受到服务器群的数量

75CDN

内容分发⽹络,基本思路是尽可能避开互联⽹上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。

78前后端路由差别

后端每次路由请求都是重新访问服务器
前端路由实际上只是 JS 根据 URL 来操作 DOM 元素,根据每个⻚⾯需要的去服务端请求数据,返回数据后和模板进⾏组合

79谈谈你对重构的理解

⽹站重构:在不改变外部⾏为的前提下,简化结构、添加可读性,⽽在⽹站前端保持⼀致的⾏为。也就是说是在不改变UI的情况下,对⽹站进⾏优化, 在扩展的同时保持⼀致的UI
对于传统的⽹站来说重构通常是:
表格( table )布局改为 DIV+CSS
使⽹站前端兼容于现代浏览器(针对于不合规范的 CSS 、如对IE6有效的)
对于移动平台的优化
针对于 SEO 进⾏优化

80什么样的前端代码是好的

⾼复⽤低耦合,这样⽂件⼩,好维护,⽽且好扩展。
具有可⽤性、健壮性、可靠性、宽容性等特点

87 [] == ![] // -> true

// [] 转成 true,然后取反变成 false
[] == false
[] == ToNumber(false)
[] == 0
ToPrimitive([]) == 0
// [].toString() -> ‘’
‘’ == 0
0 == 0 // -> true

89什么是事件代理

如果⼀个节点中的⼦节点是动态⽣成的,那么⼦节点需要注册事件的话应该注册在⽗节点上

事件代理的⽅式相对于直接给⽬标注册事件来说,有以下优点
节省内存
不需要给⼦节点注销事件

91很多⼈不知道的是,重绘和回流其实和 Event loop 有关。

当 Event loop 执⾏完 Microtasks 后,会判断 document 是否需要更新。因为浏览器是 60Hz 的刷新率,每 16ms 才会更新⼀次。然后判断是否有 resize 或者 scroll ,有的话会去触发事件,所以 resize 和scroll 事件也是⾄少 16ms 才会触发⼀次,并且⾃带节流功能。
判断是否触发了 media query
更新动画并且发送事件
判断是否有全屏操作事件
执⾏ requestAnimationFrame 回调
执⾏ IntersectionObserver 回调,该⽅法⽤于判断元素是否可⻅,可以⽤于懒加载上,但是兼容性不好
更新界⾯
以上就是⼀帧中可能会做的事情。如果在⼀帧中有空闲时间,就会去执⾏requestIdleCallback 回调

92’a’ + + ‘b’ // -> “aNaN”

+‘b’ NaN

97 预加载

在开发中,可能会遇到这样的情况。有些资源不需要⻢上⽤到,但是希望尽早获取,这时候就可以使⽤预加载
预加载其实是声明式的 fetch ,强制浏览器请求资源,并且不会阻塞 onload 事件
预加载可以⼀定程度上降低⾸屏的加载时间,因为可以将⼀些不影响⾸屏但重要的⽂件延后加载,唯⼀缺点就是兼容性不好

98预渲染

可以通过预渲染将下载的⽂件预先在后台渲染,可以使⽤以下代码开启预渲染
预渲染虽然可以提⾼⻚⾯的加载速度,但是要确保该⻚⾯百分百会被⽤户在之后打开,否则就⽩⽩浪费资源去渲染


99懒执⾏与懒加载

懒执⾏就是将某些逻辑延迟到使⽤时再计算。该技术可以⽤于⾸屏优化,对于某些耗时逻辑并不需要在⾸屏就使⽤的,就可以使⽤懒执⾏。懒执⾏需要唤醒,⼀般可以通过定时器或者事件的调⽤来唤醒
懒加载
懒加载就是将不关键的资源延后加载
懒加载的原理就是只加载⾃定义区域(通常是可视区域,但也可以是即将进⼊可视区域)内需要加载的东⻄。对于图⽚来说,先设置图⽚标签的 src 属性为⼀张占位图,将真实的图⽚资源放⼊⼀个⾃定义属性中,当进⼊⾃定义区域时,就将⾃定义属性替换为 src 属性,这样图⽚就会去下载资源,实现了图⽚懒加载
懒加载不仅可以⽤于图⽚,也可以使⽤在别的资源上。⽐如进⼊可视区域才开始播放视频等

102密码安全

加盐
对于密码存储来说,必然是不能明⽂存储在数据库中的,否则⼀旦数据库泄露,会对⽤户造成很⼤的损失。并且不建议只对密码单纯通过加密算法加密,因为存在彩虹表的关系
通常需要对密码加盐,然后进⾏⼏次不同加密算法的加密
但是加盐并不能阻⽌别⼈盗取账号,只能确保即使数据库泄露,也不会暴露⽤户的真实密码。⼀旦攻击者得到了⽤户的账号,可以通过暴⼒破解的⽅式破解密码。对于这种情况,通常使⽤验证码增加延时或者限制尝试次数的⽅式。
加盐也就是给原密码添加字符串,增加原密码⻓度sha256(sha1(md5(salt + password + salt)))

且⼀旦⽤户输⼊了错误的密码,也不能直接提示⽤户输错密码,⽽应该提示账号或密码错误
前端加密
虽然前端加密对于安全防护来说意义不⼤,但是在遇到中间⼈攻击的情况下,可以避免明⽂密码被第三⽅获取

103this 对象的理解

普通函数

this 总是指向函数的直接调用者

如果有 new 关键字,this 指向 new 出来的实例对象

在事件中,this 指向触发这个事件的对象

IE 下 attachEvent 中的 this 总是指向全局对象 Window

箭头函数中,函数体内的this对象,就是定义时所在作用域的对象,而不是使用时所在的作用域的对象。

104如何派发事件

(dispatchEvent)(如何进行事件广播?)

W3C: 使用 dispatchEvent 方法

IE: 用 fireEvent 方法

105运行机制

  1. 在执行栈中执行一个宏任务。

  2. 执行过程中遇到微任务,将微任务添加到微任务队列中。

  3. 当前宏任务执行完毕,立即执行微任务队列中的任务。

  4. 当前微任务队列中的任务执行完毕,检查渲染,GUI线程接管渲染。

  5. 渲染完毕后,js线程接管,开启下一次事件循环,执行下一次宏任务(事件队列中取)。

微任务:process.nextTick、MutationObserver、Promise.then catch finally

**宏任务:**I/O、setTimeout、setInterval、setImmediate、requestAnimationFrame

109实现简单promise

// 三个常量用于表示状态const PENDING = 'pending'const RESOLVED = 'resolved'const REJECTED = 'rejected'function MyPromise(fn) {  const that = this  this.state = PENDING  // value 变量用于保存 resolve 或者 reject 中传入的值  this.value = null  // 用于保存 then 中的回调,因为当执行完 Promise 时状态可能还是等待中,这时候应该把 then 中的回调保存起来用于状态改变时使用  that.resolvedCallbacks = []  that.rejectedCallbacks = []  function resolve(value) {    // 首先两个函数都得判断当前状态是否为等待中    if(that.state === PENDING) {      that.state = RESOLVED      that.value = value      // 遍历回调数组并执行      that.resolvedCallbacks.map(cb=>cb(that.value))    }  }  function reject(value) {    if(that.state === PENDING) {      that.state = REJECTED      that.value = value      that.rejectedCallbacks.map(cb=>cb(that.value))    }  }  // 完成以上两个函数以后,我们就该实现如何执行 Promise 中传入的函数了  try {    fn(resolve,reject)  }catch(e){    reject(e)  }}// 最后我们来实现较为复杂的 then 函数MyPromise.prototype.then = function(onFulfilled,onRejected){  const that = this  // 判断两个参数是否为函数类型,因为这两个参数是可选参数  onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v=>v;  onRejected = typeof onRejected === 'function' ? onRejected : (e)=> { throw e };  // 当状态不是等待态时,就去执行相对应的函数。如果状态是等待态的话,就往回调函数中 push 函数  if(this.state === PENDING) {    this.resolvedCallbacks.push(onFulfilled)    this.rejectedCallbacks.push(onRejected)  }  if(this.state === RESOLVED) {    onFulfilled(that.value)  }  if(this.state === REJECTED) {    onRejected(that.value)  }}
//使用let promise=new MyPromise((resolve,reject)=>{  //请求成功  let res='dddd';  if(true){    resolve(res)  }else {    reject()  }});promise.then(res=>{  console.log(res)   //ddd})

114. instanceof的原理

// 思路:右边变量的原型存在于左边变量的原型链上function instanceOf(left, right) {  let leftValue = left.__proto__  let rightValue = right.prototype  while (true) {    if (leftValue === null) {      return false    }    if (leftValue === rightValue) {      return true    }    leftValue = leftValue.__proto__  }}

115. Object.create的基本实现原理

// 传入的对象的原型
function create(obj) {
  function F() {}
  F.prototype = obj
  return new F()
}

123. 实现一个双向数据绑定(看es6)

133

当按百分比设定一个元素的高度时,它是相对于父容器的高度计算的。但是,对于一些表示竖向距离的属性,例如 padding-top , padding-bottom , margin-top , margin-bottom 等,当按百分比设定它们时,依据的是父容器的宽度,而不是高度。

135你对line-height是如何理解的

行高是指一行文字的高度,具体说是两行文字间基线的距离。CSS中起高度作用的是height和line-height,没有定义height属性,最终其表现作用一定是line-height。
单行文本垂直居中:把line-height值设置为height一样大小的值可以实现单行文字的垂直居中,其实也可以把height删除。
多行文本垂直居中:需要设置display属性为inline-block。

137如果需要手动写动画,你认为最小时间间隔是多久

多数显示器默认频率是60Hz,即1秒刷新60次,所以理论上最小间隔为1/60*1000ms = 16.7ms

139position跟display、overflow、float这些特性相互叠加后会怎么样?

display属性规定元素应该生成的框的类型;position属性规定元素的定位类型;float属性是一种布局方式,定义元素在哪个方向浮动。

类似于优先级机制:position:absolute/fixed优先级最高,有他们在时,float不起作用,display值需要调整。float 或者absolute定位的元素,只能是块元素或表格。

141 CSS里的visibility属性有个collapse属性值?在不同浏览器下以后什么区别?

当一个元素的visibility属性被设置成collapse值后,对于一般的元素,它的表现跟hidden是一样的。

chrome中,使用collapse值和使用hidden没有区别。

firefox,opera和IE,使用collapse值和使用display:none没有什么区别。

142全屏滚动的原理是什么?用到了CSS的哪些属性?

原理:有点类似于轮播,整体的元素一直排列下去,假设有5个需要展示的全屏页面,那么高度是500%,只是展示100%,剩下的可以通过transform进行y轴定位,也可以通过margin-top实现

overflow:hidden;transition:all 1000ms ease;

145关于浮动,以下是正确的说法:

如果有非浮动元素和浮动元素同时存在,并且非浮动元素在前,则浮动元素不会高于非浮动元素;

行内元素与浮动元素发生重叠,边框、背景、内容都会显示在浮动元素之上;

块级元素与浮动元素发生重叠,边框、背景会显示在浮动元素之下,内容会显示在浮动元素之上

146关于上面两行代码显示结果说法正确和错误的是



两者都可以用来绘制日历;(对)

后者可以显示本地时间,且时间可以修改;(对)

147以下哪些方法可以优化滚动性能?

在滚动中对滚动函数进行节流处理;

滚动中减少导致重绘的操作;

滚动中减少导致重排的操作;

通过给滚动内的子元素开启硬件加速

148如何使用 css 在标题元素

前插入图像文件

h2::before{content: url(…)}

149Background-position属性

用处:配合background-image属性一起使用,用于设置背景图片在盒子中的位置

参数:xpos ypos |x% y% |x y三种,

如果只写第一个水平方向的参数,第二个垂直方向的参数会默认为:center|50%|容器高度的一半px

Xpos:规定水平方向的对齐方式,值有left,right,center

Ypos:规定垂直方向的对齐方式,值有top,bottom,center

x%:规定图片水平方向的距离。你会不会以为这个x%就是父级容器宽度的x%?那你就想错了哦,这里的x%指的是父级容器的宽度减去图片的宽度后的差值的x%。

举个栗子:background-position:50%,20%;

图片的宽度为 imgwidth:100px;高度为 imgheight:100px;

容器的宽度为 conwidth:200px;高度为 conheight:200px;

那么此时图片的左顶点距离容器的左顶点的水平距离就是(conwidth-imgwidth)50%=50px,而不是conwidth50%=100px;由此也可以算出图片的左顶点距离容器的左顶点的垂直距离为20px

150

padding是边框和内容的分割,这部分必然是透明的,除非设置背景

margin也可以透明,也可以显示背景,它显示的背景是父元素的背景。而padding是显示当前元素的背景。


vw:基于视口的宽度 vh:基于视口的高度,视口被均分成100个单位

vw:viewpoint width,视窗宽度,1vw等于视窗宽度的1%。

vh:viewpoint height,视窗高度,1vh等于视窗高度的1%。

vmin:vw和vh中较小的那个。

vmax:vw和vh中较大的那个。

pt :印刷业上常使用的单位,磅的意思,一般用于页面打印排版。


a标签不能套a标签

有序列表的小写字母如果大于26项再次从 'aa’开始


每个选择器最多只能出现一个伪元素,伪类的个数没有限制


margin: top horizontal bottom /三值语法 上 横向 下/

举例: margin: 1em auto 2em;

151

向搜索引擎表示该页面是html语言,并且语言为英文网站,而“en”即表示english

如果是中文页面,可将其改为 ,zh即表示中文


通常我们需要获取某个信息时,都会通过几个缩写的关键字进行检索,那么,在开发中,如何使用HTML5元素进行布局标签

The PRC was founded in 1949.结果:The PRC was founded in 1949.
鼠标在结果的PRC上时会显示People’s Republic of China


在Blink和Webkit的浏览器中,某个元素具有3D或透视变换(perspective transform)的CSS属性,会让浏览器创建单独的图层。

我们平常会使用left和top属性来修改元素的位置,但left和top会触发重布局,取而代之的更好的方法是使用translate,这个不会触发重布局。

解决浏览器渲染的性能问题时,首要目标就是要避免层的重绘和重排。

滥用硬件加速会导致严重性能问题,因为它增加了内存使用,并且它会导致移动端电池寿命减少。


关于web表单登录中用到的图形验证码的实现,发送到客户端的只有图片形式的验证码,服务器端保存cookie对应的图形验证码的正确


在html代码段中,可使“Welcome”在浏览器中从左向右滚动显示的是

	Welcome!

a元素可以不使用href这个属性,此时为超链接的一个占位符;


在使用table表现数据时,有时候表现出来的会比自己实际设置的宽度要宽,为此需要设置哪些属性

(多)cellpadding=”0” cellspacing=”0”

单元格边距(表格填充)(cellpadding) – 代表表格边框与单元格补白的距离,也是单元格补白之间的距离。

单元格间距(表格间距)(cellspacing) – 代表单元格外面的一个距离,用于隔开单元格与单元格空间;


MVC是一种常见的架构。描述正确的时:React

模型变更之后,只有控制器(Controller)才能驱动视图变更或重新渲染视图。

任何系统都可以使用MVC的设计理念;

模型层里面放的是业务逻辑,视图层有很多表现形式。

React属于MVC框架,是V层,单项数据绑定,可以设置为双向数据绑定


关于跨域的描述正确的是:

CSS文件的加载不受跨域的影响;图片等资源文件加载可以跨域,src本质是get请求,但文字就不一定了,有的是不允许跨域请求的。

‘window.onerror’方法默认情况下无法获取跨域脚本的报错详情;

canvas中使用drawimage贴图会受跨域的影响,解决方案1:如果图片不大不多可以使用base64,解决方案2:实例的image对象的设置img.crossOrigin = ' ';并且在服务器端设置Access-Control-Allow-Origin:*(或运行的域名);


我可以 不可以,a标签没有设置href属性时不能获取到焦点

我可以 这样便可以了。
tabindex:0 或-1 或x
0:tab键可获取焦点;
-1:tab键不可获取焦点;
x:x>0,x越小获取焦点优先级越高;


对于iframe的说法,正确的是:

iframe是用来在网页中插入第三方页面

Iframe的创建比一般的DOM元素慢了1-2个数量级;

Iframe标签会阻塞页面的加载;

局限:
1、创建比一般的 DOM 元素慢了 1-2 个数量级
iframe 的创建比其它包括 scripts 和 css 的 DOM 元素的创建慢了 1-2 个数量级,使用 iframe 的页面一般不会包含太多 iframe,所以创建 DOM 节点所花费的时间不会占很大的比重。但带来一些其它的问题:onload 事件以及连接池(connection pool)
2、阻塞页面加载
及时触发 window 的 onload 事件是非常重要的。onload 事件触发使浏览器的 “忙” 指示器停止,告诉用户当前网页已经加载完毕。当 onload 事件加载延迟后,它给用户的感觉就是这个网页非常慢。window 的 onload 事件需要在所有 iframe 加载完毕后(包含里面的元素)才会触发。在 Safari 和 Chrome 里,通过 JavaScript 动态设置 iframe 的 SRC 可以避免这种阻塞情况
3、唯一的连接池
浏览器只能开少量的连接到 web 服务器。比较老的浏览器,包含 Internet Explorer 6 & 7 和 Firefox 2,只能对一个域名(hostname)同时打开两个连接。这个数量的限制在新版本的浏览器中有所提高。Safari 3+ 和 Opera 9+ 可同时对一个域名打开 4 个连接,Chrome 1+, IE 8 以及 Firefox 3 可以同时打开 6 个绝大部分浏览器,主页面和其中的 iframe 是共享这些连接的。这意味着 iframe 在加载资源时可能用光了所有的可用连接,从而阻塞了主页面资源的加载。如果 iframe 中的内容比主页面的内容更重要,这当然是很好的。但通常情况下,iframe 里的内容是没有主页面的内容重要的。这时 iframe 中用光了可用的连接就是不值得的了。一种解决办法是,在主页面上重要的元素加载完毕后,再动态设置 iframe 的 SRC。
4、不利于 SEO
搜索引擎的检索程序无法解读 iframe。另外,iframe 本身不是动态语言,样式和脚本都需要额外导入。


onchange 是失去焦点且内容改变才会执行函数,如果内容不变则不执行;
onblur 不论内容是否改变,只要失去焦点,就会执行函数;


DHTML具备的三个主要优点是:

​ (多)动态样式、动态内容、动态定位

DHTML是Dynamic HTML的简称,就是动态的HTML(标准通用标记语言下的一个应用),是相对传统的静态的html而言的一种制作网页的概念。
DHTML 将 HTML、JavaScript、DOM 以及 CSS 组合在一起,用于创造动态性更强的网页。通过 JavaScript 和 HTML DOM,能够动态地改变 HTML 元素的样式。

DHTML实现了网页从Web服务器下载后无需再经过服务的处理,而在浏览器中直接动态地更新网页的内容、排版样式和动画的功能。

html+css+javascript(或其他脚本)的优点:html确定页面框架,css和脚本决定页面样式、动态内容和动态定位。

DHTML 的动态样式的作用是:使网页作者改变内容的外部特征而不强调用户再次下载全部内容

动态内容(Dynamic Content):动态地更新网页内容,可“动态”地插入、修改或删除网页的元件,如文字、图像、标记等。


关于页面加载过程,描述正确的是:

由于html的层次结构已经是树状结构,因此可以实现边加载边生成DOM树;

页面所有资源加载完毕后,会触发onload事件;

css加载不会阻塞DOM树的解析 ;
css加载会阻塞DOM树的渲染 ;
css加载会阻塞后面js语句的执行


关于XML、JSON、HTML5的描述:

JSON比XML在数据编码上更具有效率,更节约时间,数据的体积小,传递的速度更快些;

JSON与JavaScript的交互更加方便,更容易解析处理,更好的数据交互;(对)

XML对数据的类型描述表达比JSON更丰富;(对)

存在一些数据库,直接支持XML或JSON数据的操作,如mongodb,postgresql;(对)

HTML5是一种特殊的XML;(错)

HTML5在跨系统交互面是一种理性的交换格式;(错)

XML比JSON更能表达结构化数据;(错)


对象无初始值或者其值为 0、-0、null、""、false、undefined 或者 NaN,那么对象的值为 false;除了上面几个,它值都为 true(即使值为字符串 “false” )

console.log(({}false)?true:false); // => console.log((NaN0)?true:false);

布尔类型与其它任何类型进行比较,布尔类型将会转换为number类型。

Number转换类型的参数如果为对象返回的就是NaN,

那么Number({})返回的就是NaN

下面几个都会转化为0:

Number()

Number(’’)

Number([])

Number(0)

Number(‘0’)

Number([0])

Number(false)

Number(null)


放在HTML里的哪一部分JavaScript会在页面加载的时候被执行?

​ (单)标签部分

在HTML body部分中的JavaScripts会在页面加载的时候被执行。放在body部分的脚本通常被用来生成页面的内容。
在HTML head部分中的JavaScripts会在被调用的时候才执行。把脚本放在head部分中时,可以保证脚本在任何调用之前被加载。
之所以把js放在body之后,是为了预防外部js文件过多时,浏览器呈现页面出现延迟,延迟期间浏览器的窗口一片空白。


拖放是HTML5标准的组成部分,若想要把drag1图片放入div1块中,拖放方法如下:

function allowDrop(ev){ 	ev.preventDefault();}function drag(ev){ 	ev.dataTransfer.setData("Text",ev.target.id);}function drop(ev){     ev.preventDefault();    var data=ev.dataTransfer.getData("Text");    ev.target.appendChild(document.getElementById(data));} 则,如下HTML代码正确的是()

创建带有id属性的DOM元素有什么副作用?

​ (单)会创建同名的全局变量;

如果一个元素拥有ID属性,那么ID属性的属性值就会成为window对象的属性名.


html5新增了manifest标签,他有什么作用?

​ (单)应用缓存资源清单

manifest 文件是一个简单的文本文件,列举出了浏览器用于离线访问而缓存的资源。


哪个元素定义了元素的参数?

​ (单)

param用来为object或applet元素定义的对象或小程序进行初始化参数设置


WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。

在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。


一个页面title元素只能有一个;

一个页面main元素只能有一个(多个,其他隐藏也可以),因为

标签规定文档的主要内容,
元素不能是以下元素的后代: