前端面试八股文(详细版)—上

本文将详细讲解 HTML 、CSS 、JavaScript 、计算机网络知识等方面的内容,Vue 、React 、git 、项目开发实例等内容放在下篇,预祝各位成功上岸!

 

第一板块:JavaScript

ES6 新增内容

1、模板字符串 变量名写在 ${} 中,${} 中可以放入 JavaScript 表达式

2、箭头函数

3 class 类的继承

  class Animal {}
  class Dog extends Animal {
   constructor(name) {
​    super();
​    // this.name = name
   }
  }

3、module

4、promise

5、const / let

6、 扩展运算符(...)

  • 用于取出参数对象所有可遍历属性然后拷贝到当前对象
  • 可用于合并两个对象

7、 解构赋值

  • 解构赋值语法是一种 Javascript 表达式。通过解构赋值,可以将属性/值从对象/数组中取出,赋值给其他变量。
let a, b, rest;
[a, b] = [10, 20];

console.log(a);
// expected output: 10

console.log(b);
// expected output: 20

[a, b, ...rest] = [10, 20, 30, 40, 50];

console.log(rest);
// expected output: Array [30,40,50]

8、 Symbol 数据类型 一种新的原始数据类型,主要是为了避免属性名的重复

9、Map 一种新的数据结构,类似对象,Set 一种新的数据结构,类似数组

普通函数和箭头函数的区别?

1、箭头函数没有自己的 this 指向,它的 this 指向来源于它的上级,并且继承而来的 this 指向是无法改变的。

2、 箭头函数由于没有自己的 this,所以不能作为构造函数。

3、箭头函数中没有 arguments(形参数组),但是可以访问外围函数的arguments对象

补充:ES6 箭头函数中的 this 和所在环境(外层)中的 this 指向一致

如何改变 this 指向

可以使用call()、apply()、bind() 来改变 this

Call bind apply的原理和区别

- call 方法 call()是 apply()的一颗语法糖,作用和 apply()一样,同样可实现继承,唯一的区别就在于 call()接收的是参数列表,而 apply()则接收参数数组。

- bind 方法 bind()的作用与 call()和 apply()一样,都是可以改变函数运行时上下文,区别是 call()和 apply()在调用函数之后会立即执行,而 bind()方法调用并改变函数运行时上下文后,返回一个新的函数,供我们需要时再调用.

1、第一个参数都是 this 的指向对象

2、 apply 的第二个参数是函数接受的参数,以数组的形式传入,且当第一个参数为null、undefined的时候,默认指向window(在浏览器中),使用apply方法改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次。

3、call 传入的第二个参数是一个参数列表(注意和apply传参的区别)。当一个参数为null或undefined的时候,表示指向window(在浏览器中),和apply一样,call也只是临时改变一次this指向,并立即执行。 

4、 bind 传入的第二个参数也是一个参数列表(但是这个参数列表可以分多次传入,call则必须一次性传入所有参数),但是它改变this指向后不会立即执行,而是返回一个永久改变this指向的函数,供我们需要时再调用.。

 promise 用法以及相关原理 用法 有那些 API

1、promise是异步编程的一种解决方案,解决多个异步方法串行的问题,比如回调地狱等;

2、promise,简单地说就是一个容器,里面保存着某个未来才会结束的事件,从语法说promise是一个对象,从他可以获取异步操作的消息。promise提供统一的api,各种操作都可以用相同的方法进行处理.;

3、它接受一个 function 作为参数。function 中有两个形参,第一个表示请求成功的回调,第二个表示请求失败的回调,分别是 resolve 和 reject ;

4、.then 在成功的时候触发 .catch 在失败的时候触发

5、promise 的状态不受外界影响不可逆,三个状态:pending(进行中)、fulfilled(已成功)、rejected(已失败)

  • promise对象的状态改变只有两种可能:从pending变为fulfilled或从pending变为rehected;

6、有两个很重要的 api:

  • Promise.all()   表示所有的 Promise 数组中的方法都成功之后触发

         返回一个新的promise,只有所有的promise都成功才能成功,只要有一个失败了就直接失败;

  • Promise.race()  表示数组中只要有一个完成就结束

       返回一个promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝;

回调地狱

回调函数中嵌套回调函数的情况就叫做回调地狱。它就是为是实现代码顺序执行而出现的一种操作,它会造成我们的代码可读性非常差,后期不好维护。

promise 和 async await 的区别

1、Promise是 ES6 中处理异步请求的语法,使用 .then() 来实现链式调用,使用 .catch() 来捕获异常。

2、async/await 是对 Promise 的升级,async用于声明一个函数是异步的,await是等待一个异步方法执行完成

3、async/await 用同步的写法写异步(await一个Promise对象),async/await 的捕获异常可以使用 try/catch 语法。(也可以使用 .catch 语法)用同步的方法写异步的代码;

let const var 的区别

var 关键字:

  1. var 定义变量,可以声明同名变量,可以不进行初始化;(不初始化的情况下保存一个特殊值 undefined )
  2. var 不仅可以改变保存的值,也可以改变值的类型(合法但不推荐);
  3. var 定义的变量在函数作用域内有效;
  4. var 声明变量存在变量提升,var 声明的变量可以挂载在 window 上;

let 声明:

  1. let 定义变量,可以不进行初始化;(不初始化的情况下保存一个特殊值 undefined )
  2. let 不仅可以改变保存的值,也可以改变值的类型(合法但不推荐);
  3. let 用来定义局部变量,仅在块级作用域内有效;
  4. let 不允许重复声明;
  5. 不存在变量提升的现象,所以一定要在定义后使用,否则报错(暂时性死区);
  6. 在全局作用域中用 let 声明变量不会成为 window对象的属性;

const 声明:

  1. const 定义的是常量,必须进行初始化(设置初始值);
  2. const 定义好之后“不能改变”;(不能改变栈里面的数据,堆里面的数据可改变;例如数字不可变,对象的属性等可变)
  3. 仅在块级作用域内有效;
  4. const 不允许重复声明;
  5. 在全局作用域中用 const 声明变量不会成为 window对象的属性;

详细分析查看:https://blog.csdn.net/leoxingc/article/details/127813133

常见数组方法

  1.  push()           向数组尾部添加元素,返回添加后的数组长度,原数组改变 
  2.  pop()             从数组的尾部删除一个元素,返回删除的元素,原数组改变 
  3.  unshift()         向数组头部添加元素,返回添加后的数组长度,原数组改变 
  4.  shift()             从数组的头部删除一个元素,返回删除的元素,原数组改变 
  5.  Slice()            提取数组,(1 起 2 止止不算)原数组不变 
  6.  splice()          剪接数组,(1 起 2 长 3 添加)原数组改变               
  7.  reverse()        反转数组,原数组改变 
  8. sort()              按位比较
  9. arr.sort(function(a,b){return a - b;});               从小到大
  10. arr.sort(function(a,b){return b - a;});            从大到小      
  11. Join()                     参数最为连接字符,连接数组,转换为字符串,原数组不变 
  12. concat()                 合并数组,原数组不变 arr1.concat(arr2,arr3)        
  13.  find 查找符合条件的项
  14.  findIndex 查找符合条件项目的下标
  15. toString()把数组转字符串(之间默认用逗号隔开)

ES5 数组的常用方法

  1. indexOf()                       查找数组中某元素第一次出现的索引,若无返回-1
  2.  lastindexOf()                查找数组中某元素最后一次出现的索引,若无返回-1    
  3. forEach()                       遍历数组,不接受返回值        
  4. map()                          映射数组,接受返回值             
  5. Filter()                         筛选满足条件数组 
  6. Every()                       判断数组里每一个元素是否符合条件
  7. Some()                       判断数组里是否有一个符合条件的元素
  8. reduce()                      数组值累加(两个值累加完传递给第一个元素,直到最后)

遍历

1、基本 for 循环

 // for
      var arr = [1, 2, 3];
      for (var i = 0; i < arr.length; i++) {
        console.log(arr[i]);    // 1,2,3
      }

2、for...of...遍历

      // for...of...
      var arr = [1, 2, 3];
 
      for (var i of arr) {
        console.log(arr[i]);  // 1,2,3
      }

3、for...in...遍历

      // for...in...
      var arr = [1, 2, 3];
 
      for (var i in arr) {
        console.log(arr[i]);  // 1,2,3
      }

4、forEach()遍历


// forEach( item, index, arr )
var arr = [1, 2, 3];
arr.forEach((item, index, arr) => { // item为arr的元素,index为下标,arr原数组
    console.log(item); // 1, 2, 3
    console.log(index); // 0, 1, 2
    console.log(arr); // [1, 2, 3]
});

5、map() 映射


      // map() 映射
      var arr = [1, 2, 3];
      var arr1 = arr.map((item, index, arr) => { 
         // item为arr的元素,index为下标,arr原数组
        console.log(item); // 1, 2, 3
        console.log(index); // 0, 1, 2
        console.log(arr); // [1, 2, 3]
        return item * 2; // 返回一个处理过的新数组[2, 4, 6]
      });
      console.log(arr);
      console.log(arr1);  // 处理过的新数组[2, 4, 6]

6、filter() 

      var arr = [1, 2, 3];
      var arr1 = arr.filter(function (item, index, arr) {
        // item为arr的元素,index为下标,arr原数组
        console.log(item); // 1, 2, 3
        console.log(index); // 0, 1, 2
        console.log(arr); // [1, 2, 3]
        return item > 2; // 返回一个过滤过的新数组[3]
      });
      console.log(arr);
      console.log(arr1); // 过滤过的新数组[3]

7、some()

      // some()
      var arr = [1, 2, 3];
      arr.some((item, index, arr) => {
        // item为数组中的元素,index为下标,arr为目标数组
        console.log(item); // 1, 2, 3
        console.log(index); // 0, 1, 2
        console.log(arr); // [1, 2, 3]
      });

8、every()

      // every()
      var arr = [1, 2, 3];
      var arr1 = arr.every((item, index, arr) => {
        // item为数组中的元素,index为下标,arr为目标数组
        console.log(item); // 1, 2, 3
        console.log(index); // 0, 1, 2
        console.log(arr); // [1, 2, 3]
        return item > 0; // true
      });
      console.log(arr); // [1, 2, 3]
      console.log(arr1); // true

9、reduce()

      // every()
      var arr = [1, 2, 3];
      var arr1 = arr.reduce((sum, item, index, arr) => {
        // item为数组中的元素,index为下标,arr为目标数组,sum为上一次调用回调函数时的返回值,
        console.log(item);
        console.log(index);
        console.log(arr);
        return sum + item; 
      }, init);

10.详细分析可查看:

前端遍历数组的方法:

 数组去重

1、利用数组的 indexOf 方法,新建一个空数组,循环遍历旧数组,判断空数组中是否有当前的元素,如果有就跳过,如果没有就执行 push 方法。

let arr = [1, 1, 2, 2, 3, 3, 4, 5];
      let newArr = [];
      arr.forEach(item => {
        if (newArr.indexOf(item) < 0) {
          newArr.push(item);
        }
      });

2、利用数组的 splice 方法,先利用 sort 方法对数组进行排序,然后循环遍历数组,比较前一项与后一项是否相同,如果相同就执行 spilce 方法删除当前项。

3. 利用 ES6 中 Set 不能存放相同元素的特点,配合...展开运算符进行去重。

       let arr=[1,2,3,4,3,2,1,5,3];

       let set=new Set(arr);

       //因为set结构并不是数组,所以需要转为数组

       set=[...set];

4. lodash 插件也可以去重。

判断是不是数组

let a = [1, 3, 4];

Array.isArray(a); //true
a instanceof Array; //true
a.constructor === Array; //true
Object.prototype.toString.call(a) === "[object Array]"; //true

for in 和 for of 的区别

for...in 只能获得对象的键名,对数组来说是下标,对象是属性名。并且手动添加的属性也能遍历到;

for...of 只能获得键值(数组),遍历对象会报错;

数组排序

(1)冒泡排序:数组中的元素两两进行比较,如果前一个比后一个大,交换值,第一轮结束

(2)选择排序:选出一个位置,这个位置上的数,和后面所有的数进行比较,如果比较出大小就交换两个数的位置

(3)/*sort排序 */

arr.sort((a,b)=>{

return a-b;

})

将伪数组转换为真数组

1、Array.from() 将伪数组转成真数组 

arr=Array.from(arr);

2、arguments   将伪数组转成真正的数组

function test (){

     arguments.__proto__ = Array.prototype;

     arguments.push(10)

     console.log(arguments)

 }

     test(1,2,3,4)

随机取值

数据中有 800 个元素,随机取一个

生成一个 0-800 之间的随机数作为数组下标

 const arr = [1,2,3,4,5,6,7...]

 // 随机获取一个下标

 // Math.random的取值范围 0=

删除某个元素

数组中有 800 个元素,删除第 701 个

arr.splice(700, 1); // splice参数一表示开始位置 参数二表示个数 后面的参数序列是用来替换的内容,如果没有就只做删除处理
filter, slice + concat;

字符串方法

 

字符串和数字相加

相加的时候会做隐式转换,数字转换为字符串,最终的结果是字符串拼接;

字符串如何转变为数字

let str = "123";

console.log(Number(str));.
console.log(str \* 1);

深拷贝和浅拷贝

浅拷贝:只拷贝第一级实现方式:...扩展运算符 Object.asign

浅拷贝:基本数据类型拷贝值,复杂数据类型,拷贝地址

深拷贝:逐层拷贝对象的每一级

实现方式:`JSON.parse(JSON.stringify(obj))`或者使用插件 lodash

深拷贝:拷贝的是值,相互之间没有影响 地址指向堆

深浅拷贝是因为引用数据类型数据存储的问题,引用数据类型会把指针存放在栈内存中,真正的值存放在堆内存中,浅拷贝只是拷贝了地址,而深拷贝则是完全拷贝,并且拷贝后的对象和原对象没有任何关联。

  1.   栈内存中放地址,堆内存中放值
  2. - 使用递归实现深拷贝。
  3. - 使用 lodash 插件中的 deepclone 来实现深拷贝。
  4. - 使用 JSON.stringfy()和 JSON.parse()来实现。
let obj = {name:'zhangsan',age:18}
let newObj = JSON.parse(JSON.stringfy(obj))

原型和原型链

每个构造函数都有一个原型,每个原型对象又有一个construtor属性指向构造函数,每个实例都有__proto__指向原型对象,原型对象上的属性方法能被实例访问。

在JS中,用 __proto__ 属性来表示一个对象的原型链。当查找一个对象的属性时,JS会向上遍历原型链,直到找到给定名称的属性为止。

JavaScript prototype(原型对象)

所有的 JavaScript 对象都会从一个 prototype(原型对象)中继承属性和方法。

所有 JavaScript 中的对象都是位于 原型链顶端的 Object  的实例。

每个对象都有一个`__proto__`属性,并且指向它的`prototype`原型对象

每个构造函数都有一个`prototype`原型对象

`prototype`原型对象里的`constructor`指向构造函数本身

原型链的终点  Object.prototype.__proto__ === null   //true

原型和原型链的详细介绍:http://t.csdn.cn/zQZMc

原型/构造函数/实例

原型(prototype): 一个简单的对象,用于实现对象的属性继承。可以简单的理解成对象的爹。每个JavaScript对象中都包含一个–proto-- (非标准)的属性指向它爹(该对象的原型),可obj.–proto–进行访问。

构造函数: 本质上是一个普通的函数,只是可以通过new来 新建一个对象的函数。

实例: 通过构造函数和new创建出来的对象,便是实例。 实例通过__proto__指向原型,通过constructor指向构造函数。

new 操作符调用构造函数的步骤

1、创建一个新对象

2、将构造函数的作用域赋给新对象(因此this指向了这个新对象)

3、执行构造函数中的代码(为这个新对象添加属性)

4、返回新对象

闭包

闭包就可以在全局函数里面操作另一个作用域的局部变量!

在函数外部可以访问函数内部的变量。

使用场景:一时半会想不到了-------(必须答时 1.函数作为参数传递。2.函数作为返回值)

function foo(){
  var local = 1
  function bar(){
    local++		//可以访问这个函数词法作用域中的变量
    return local
  }
  return bar //一个函数被当作值返回
}

var func = foo()	//外层函数执行完毕时销毁
func()	//这个通道可以访问这个函数词法作用域中的变量,即函数所需要的数据结构保存了下来,而且无法直接访问,必须通过返回的函数。

- 虽然可以保护私有变量,但用多了可能造成内存泄露。

闭包的好处:减少全局变量的定义,减少全局空间的污染;形成命名空间;

闭包的坏处:容易造成内存泄漏:一块内存空间既不能被销毁,也不能被访问,通常出现 IE 低版本;

闭包优化:由于闭包会一直占用内存空间,直到页面销毁,我们可以主动将已使用的闭包销毁,

将闭包函数赋值为null 可以销毁闭包;

闭包 this 执行问题:this指向window对象(因为匿名函数的执行具有全局性,所以其this对象指向window);

遇到内存泄漏的问题

当不断向堆中存储数据,而不进行清理,这就是内存泄漏;

当页面中元素被移除或替换时,若元素绑定的事件仍没被移除,在IE中不会作出恰当处理,此时要先手工移除事件,不然会存在内存泄露;

哪些操作会造成内存泄露

1、全局变量引起的内存泄露

2、闭包引起的内存泄露:慎用闭包

3、dom清空或删除时,事件未清除导致的内存泄漏

4、循环引用带来的内存泄露

页面实时更新

因为 HTTP 协议有一个缺陷:通信只能由客户端发起。

轮询:定时发送请求,响应请求  

websocket

js 的执行机制?微任务和宏任务

1. js 是单线程的

   所谓单线程就是一次只能执行一段代码,在执行的时候如果遇到比较耗时的操作,默认就会停下来等待这个操作完成之后继续走。这种情况下,就会出现页面卡在那里不动。为了解决这个问题 js 一般把比较耗时的操作做异步处理;

2. js 中的异步处理

   js 中存在一个异步队列,所有比较耗时的操作都会被丢在这个异步队列中。当主线程空闲(同步代码)之后会执行异步队列中的代码,这个就是 js 中的 eventloop(事件循环);

宏任务,是运行环境提供的异步操作,例如:setTimeout;

微任务,是 js 语言自身的异步操作,例如:Promise;

  在一个宏任务周期中会执行当前周期中的所有微任务,当所有的微任务都执行完成之后会进入下一个宏任务周期;

JS 中的继承

1、原型链继承

核心:将父类的实例作为子类的原型

2、构造继承

核心:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)

3、实例继承

核心:为父类实例添加新特性,作为子类实例返回

4、组合继承

核心:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用

5、寄生组合继承

核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点

ESlass 继承,constructor()和 super()关键字

super()方法用来调用父类的构造函数;

constructor 是原型对象上的一个属性,默认指向这个原型的构造函数;

 Map 与 Set

- Map

  - Map 的键可以是任意值。包括对象{ {a:1}:xxx }

  - .set() var myMap = new Map(); myMap.set(0, "zero");

  - .get()

  - .delet()

- Set

  - Set 的键名是唯一的,不能重复,undefined 和 NaN 也不重复

  - 用来去重

    var mySet = new Set([1, 2, 3, 4, 4]);

    [...mySet]; // [1, 2, 3, 4]

 js 中 Map 和 Object 有什么区别?

- Map 是 es6 新增的一种数据结构,继承自 Object,并对 Object 做了一些拓展。

- Map 的键可以是任意的数据类型,Object 不行。

- Map 是可迭代(iterable)的,可以使用 for...of 遍历,而 Object 不行。

- Map 的长度可以通过 size 直接拿到,Object 不行。

- Map 使用拓展运算符是可以直接展开的,Object 不行。

js 中的数据类型

一般数据类型:string number boolean null undefined symbol bigint

​ `BigInt`数据类型的目的是比`Number`数据类型支持的范围更大的整数值。

复杂数据类型:对象、数组、function

- 值为一个地址,地址指向真正的数据

js 中如何准确判断一个数据的数据类型?

typeof   如果是基本数据类型,使用typeof来判断,但是typeof不能用来判断引用数据类型的数据
			不能判断Null、Array等
instanceof      不能检测Null和undefined
contructor
Object.prototype.toString.call( )

typeof 区分原理

typeof原理: 不同的对象在底层都表示为二进制,在Javascript中二进制前(低)三位存储其类型信息。
typeof null 为"object", 原因是因为 不同的对象在底层都表示为二进制,在Javascript中二进制前(低)三位都为0的话会被判断为Object类型,null的二进制表示全为0,自然前三位也是0,所以执行typeof时会返回"object"。

类型判断

typeof

用 typeof 检测**null**返回是 object。在 JavaScript 中 null 表示 "什么都没有"。null 是一个只有一个值的特殊类型。表示一个空对象引用。

typeof 一个**没有值的变量**会返回 **undefined**。

null 和 undefined 的值相等,但类型不等:

  typeof "John"; // string
  typeof 3.14; // number
  typeof false; // boolean
  typeof [1, 2, 3, 4]; // object 在JavaScript中,数组是一种特殊的对象类型。 因此 typeof [1,2,3,4] 返回 object。
  typeof { name: "John" }; // object
  typeof undefined; // undefined
  typeof null; // object
  null === undefined; // false
  null == undefined; // true

instanceof

  - obj instanceof Object ,可以左边放你要判断的内容,右边放类型来进行 JS 类型判断

  - 需要知道是什么类型才能正确判断

    [1, 2] instanceof
      Array(
        // true
        function () {}
      ) instanceof
      Function(
        // true
        { a: 1 }
      ) instanceof
      Object(
        // true
        new Date()
      ) instanceof
      Date; // true

object.prototype.toString.call

  Object.prototype.toString.call(999); // "[object Number]"
  Object.prototype.toString.call(""); // "[object String]"
  Object.prototype.toString.call(Symbol()); // "[object Symbol]"
  Object.prototype.toString.call(42n); // "[object BigInt]"
  Object.prototype.toString.call(null); // "[object Null]"
  Object.prototype.toString.call(undefined); // "[object Undefined]"
  Object.prototype.toString.call(true); // "[object Boolean]
  Object.prototype.toString.call({ a: 1 }); // "[object Object]"
  Object.prototype.toString.call([1, 2]); // "[object Array]"
  Object.prototype.toString.call(new Date()); // "[object Date]"
  Object.prototype.toString.call(function () {}); // "[object Function]"

类型转换

toString(); // 转化为字符串,不可以转null和underfined
String(); // 转换为字符串,
Number(); // 转换为数字,字符串中有一个不是数值的字符,返回NaN
parseInt(); // 转换为数字,第一个字符不是数字或者符号就返回NaN
Boolean(); // 转换为布尔值

函数声明和函数赋值语句的差别:

赋值式函数需要给变量赋值,以 var、let;声明式是不需要给变量赋值,以 function 开头;

对象的常用方法

Object.assign(target,source1,source2,...)

  •   - 该方法主要用于对象的合并,将源对象 source 的所有可枚举属性合并到目标对象 target 上,此方法只拷贝源对象的自身属性,不拷贝继承的属性。
  •   - Object.assign 方法实行的是浅拷贝,而不是深拷贝,当只有一层时为深拷贝
  •   - 同名属性会替换

Object.create()

  •   - Object.create()方法接受两个参数:Object.create(obj , propertiesObject) ;
  •   - propertiesObject:可选。该参数对象是一组属性与值,该对象的属性名称将是新创建的对象的属性名称,值是属性描述符(这些属性描述符的结构与 Object.defineProperties()的第二个参数一样)。注意:该参数对象不能是 undefined,另外只有该对象中自身拥有的可枚举的属性才有效,也就是说该对象的原型链上属性是无效的。
  •   - 没有继承 Object.prototype 原型链上的属性或者方法,例如:toString(), hasOwnProperty()等方法

前端面试八股文(详细版)—上_第1张图片

 hasOwnProperty()

  •   - 判断对象自身属性中是否具有指定的属性。obj.hasOwnProperty('name')

Object.is()

  •   - 判断两个值是否相同。
    Object.is('foo', 'foo')// true
    Object.is(window, window)// true
    Object.is('foo', 'bar'); // false
    Object.is([], []); // false
    var test = { a: 1 };
    Object.is(test, test); // true
    Object.is(null, null); // true
    // 特例
    Object.is(0, -0); // false
    Object.is(-0, -0); // true
    Object.is(NaN, 0 / 0); )// true

Object.keys(obj)

  - 返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致 (两者的主要区别是 一个 for-in 循环还会枚举其原型链上的属性)

    let arr = ["a", "b", "c"];
    Object.keys(arr); //["0", "1", "2"]
    let obj = { age: 20, sex: "男" };
    Object.keys(obj); //["age", "sex"]

Object.values()

  •   - 方法返回一个给定对象自己的所有可枚举属性值的数组,值的顺序与使用 for...in 循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )。
    var obj = { 10: "a", 1: "b", 2: "c" };
    Object.values(obj); // ['b', 'c', 'a']
    var obj1 = { 0: "a", 1: "b", 2: "c" };
    Object.values(obj1); // ['a', 'b', 'c']

entries

  • - 分割对象,将对象分割为数组
    const obj = { foo: "bar", baz: 42 };
    Object.entries(obj); // [ ['foo', 'bar'], ['baz', 42] ]
    // array like object
    const obj = { 0: "a", 1: "b", 2: "c" };
    Object.entries(obj); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]
    //  string
    Object.entries("abc"); // [['0', 'a'], ['1', 'b'], ['2', 'c']]
    Object.entries(100); // []

判断两对象是否相等

1、通过JSON.stringify(obj)来判断两个对象转后的字符串是否相等

2、getOwnPropertyNames方法返回一个由指定对象的所有自身属性的属性名组成的数组。先进行长度的比较,然后进行遍历

3.Object.is(a,b)

// 手写:
function diff(obj1,obj2){
        var o1 = obj1 instanceof Object;
        var o2 = obj2 instanceof Object;
        // 判断是不是对象
        if (!o1 || !o2) {
            return obj1 === obj2;
        }

        //Object.keys() 返回一个由对象的自身可枚举属性(key值)组成的数组,
        //例如:数组返回下表:let arr = ["a", "b", "c"];console.log(Object.keys(arr))->0,1,2;
        if (Object.keys(obj1).length !== Object.keys(obj2).length) {
            return false;
        }

        for (var o in obj1) {
            var t1 = obj1[o] instanceof Object;
            var t2 = obj2[o] instanceof Object;
            if (t1 && t2) {
                return diff(obj1[o], obj2[o]);
            } else if (obj1[o] !== obj2[o]) {
                return false;
            }
        }
        return true;
    }

两个对象如果属性名和属性值都一样,他俩是否相等?为什么?

// 他俩不相等,因为对象的存储位置不一样,所以永远不相等
    function compareTwoObj(a, b) {
      return JSON.stringify(a) == JSON.stringify(b);
    }

获取对象中的所有属性名

Object.keys(obj); // 数组,所有属性名组成的数组
for (let k in obj) {
}

json 字符串如何转换为 js 对象

 js对象转字符串

JSON.stringify

// json字符串转对象

JSON.parse

如何删除对象中的一个属性

var obj = { a: 1, b: 2, c: 3 };

delete obj.c; // 删除一个属性

var strJson = `{"a": "123", "1-a": "456"}`;

面向对象

面向对象是把整个需求按照特点、功能划分,将这些存在共性的部分封装成类

面向对象的三大基本特征:封装、继承、多态

  • 封装就是把一些通用的代码或者功能封装在一个文件中
  • 继承就是子类可以继承父类的属性和方法,实现代码复用
  • 多态就是一个 function 接收的参数不一样,返回不同的结果
 //多态演示

 // 构造函数
 function Behavior () {}
 Behavior.prototype.sound = function (sound) {
     return sound
 }
 function Man () {}
 Object.setPrototypeOf(Man.prototype, Behavior.prototype)
 function Woman () {}
 Object.setPrototypeOf(Woman.prototype, Behavior.prototype)


 let man = new Man()
 console.log(man.sound('哈哈哈'))  // 哈哈哈
 let woman = new Woman()
 console.log(woman.sound('嘻嘻嘻'))  // 嘻嘻嘻

对象常用的操作

- 获取所有的属性名,Object.keys、for in

- 获取所有的属性值,Object.values

- 删除一个属性

- 动态获取属性,可以使用数组下标的方式

 

事件

js 中的常用事件绑定方法

1. 在DOM元素中直接绑定

2. 在JavaScript代码中绑定

3. 绑定事件监听函数

事件传播流程

三个阶段:捕获、事件源、冒泡

捕获是从 html 标签开始,逐层往内进行传递,到触发事件的标签为止

事件源是在当前触发事件的标签上进行传递

冒泡是从当前触发事件的标签开始逐层往外进行传递到 html 节点结束

addEventLister 的第三个参数,是一个 bool 值。默认是 false,表示在冒泡阶段触发

event 对象中的 target 和 currentTarget 有什么区别?

target 触发事件的标签

current Target 绑定事件的标签

addEventListener,第三个参数是一个 bool 值,默认是 false 表示在冒泡阶段触发事件

事件监听、事件委托

- 事件监听

  1.   addEventListener,第三个参数是一个 bool 值,默认是 false 表示在冒泡阶段触发事件
  2.   addEventListener(事件类型,处理函数,布尔值) 布尔值 I.false 事件冒泡 默认 II.true 事件捕获
  3.  使用事件监听器的好处:

         使用事件监听器方式添加事件,可以给同一个 DOM 对象添加多个相同的事件名,对应事件处理函数会依次执行

         普通事件添加方式,如果添加多个相同的事件名,后面的会覆盖前面,只会执行最后一个

  on类型的事件在事件冒泡阶段触发

  target(触发事件的标签)/currentTarget(绑定事件的标签)

  **DOM标准事件流的触发的先后顺序为:先捕获再冒泡**

  **阻止冒泡**:stopPropagation || cancelBubble

  #### 事件默认行为

  a标签的跳转,input框的输入,Submit按钮的提交,右键菜单

  **阻止默认事件**:returnValue=false || preventDeafault

- 事件委托

  1.   - 利用事件冒泡的原理,将本应该添加某个 DOM 对象上的事件委托给他的父级
  2.   - 让新增的 DOM 具有相同的事件,减少事件添加的次数,提高执行效率
  3.   - 使用场景:大量标签绑定同一事件,动态渲染的标签

事件 onxx 和 addEventListener 有什么区别

​ onClick 表示添加一个点击事件,属于属性赋值。属性多次赋值会出现覆盖,只有最后一次的赋值是有效果的

​ addEventlistener 事件委托,可以添加多次,每一次添加都会执行,它可以接收三个参数('事件名字', 回调函数, bool)

​ bool 默认是 false 表示在冒泡阶段触发

事件拖拽

01-在允许拖拽的节点元素上,使用 on 来监听 mousedown(按下鼠标按钮)事件,鼠标按下后,克隆当前节点

02-监听 mousemove(鼠标移动)事件,修改克隆出来的节点的坐标,实现节点跟随鼠标的效果

03-监听 mouseup(放开鼠标按钮)事件,将原节点克隆到鼠标放下位置的容器里,删除原节点,拖拽完成。

DOM/BOM

BOM 是 browser object model 的缩写,简称浏览器对象模型。是用来获取或设置浏览器的属性、行为,例如:新建窗口、获取屏幕分辨率、浏览器版本号等。 比如 alert();弹出一个窗口,这属于 BOM,核心对象是 window。

DOM 是 Document ,简称文档对象模型。是用来获取或设置文档中标签的属性,例如获取或者设置 input 表单的 value 值。document.getElementById("").value; 这属于 DOM,核心对象是 标签。

说出几个常用的 BOM 对象和方法

  1. alert('提示信息')
  2. confirm("确认信息")
  3. prompt("弹出输入框")
  4. open("url 地址",“black 或 self”,“新窗口的大小”)
  5. close() 关闭当前的网页

常见的 dom 元素选择方式有哪些

  • getElementById
  • getElementsByClassName
  • getElementsByTagName
  • querySelector
  • querySelectorAll

dataset 数据集

是为标签添加的属性 data-开头的这些,在 js 中可以直接通过使用 dom 对象的 dataset 属性获取

设计模型

工厂模式、单例模式、原型模式,组合模式,发布-订阅模式

jQuery 优点和缺点

优点:出色的浏览器兼容性;出色的DOM操作的封装,可以进行快速的DOM元素操作;支持链式操作,支持插件

缺点:不能向后兼容,一个页面使用多个插件容易冲突,对动画和特效的支持差;

axios 和 ajax

 Ajax 核心使用XMLHttpRequest对象,多个请求之间如果有先后关系的话,就会出现回调地狱

 axios支持 Promise API,提供了一些并发请求的接口,自动转换JSON数据,体积也较小;

什么是 mvc

​ mvc 是一种开发模式

​ model,用来存储数据

​ view,用来展示数据

​ controller [kənˈtrəʊlə(r)] ,用来控制数据的展示方式

 


第二板块:计算机网络

https,使用 ssl 证书进行加密传输 防止网络抓包 保证信息安全

js 中发起请求的方式:xhr、fetch、websocket

介绍 http 请求报文

请求行------请求行有请求方法、URL和HTTP协议版本3个字段

请求头(携带数据) cookies   token    content-type

请求体   传输数据   发起post或get请求

数据传输的格式

  1.     json        '{"name":"zhangsan"}'
  2.     urlencoded  name=Tom&&age=18
  3.     form-data   此格式数据常常用于文件上传

常见状态码

状态码:200 多,300 多,400 多,500 多

200:成功

301:永久重定向、302:临时重定向

401:未授权

403:服务器拒绝访问

404:页面找不到

500:服务器错误

设计模式

- 单例模式

- 观察者模式

- 工厂模式

- 发布订阅模式

get 和 post 的区别

get 用来获取数据,参数传递的时候在 url 中可以直接看到,不太安全。传递的数据量比较少,可以加入收藏夹

post 用来传递大量数据,数据在请求体中进行传递,url 地址中看不到,相对于 get 请求更安全

1、常见的请求方式

  •   get 获取数据
  •   post 新增数据
  •   put/patch 修改数据
  •   delete 删除数据

2、 CRUD(增删改查)

  • Create
  •   Read
  •   Update
  •   Delete

3、SSR 服务器端渲染

  • php
  • java
  • python
  • node.js

4、get和post的区别

  •     get请求参数明文传输,在url中传递
  •     post请求在请求体中传输
  •     post请求相对get请求更安全一些
  •     post请求传输的参数大小比get请求大
  •     get传送的数据量不能大于2kb,post传送的数据量较大
  •     get请求可以加入收藏夹
  •     get请求常常用于获取数据,请求速度快

5、get请求传递的参数为什么有大小限制?

    get请求在url中传递,不同浏览器对url长度有限制

http 三次握手以及常见的状态码?

- 第一次握手是客户端给服务端发送请求,请求建立连接。

- 第二次握手是服务端给客户端发送请求,表示已经收到客户端的请求,并且同意建立连接。

- 第三次握手是客户端向服务端发送请求,表示确认收到服务端发送的信息。

- 三次握手的原因是为了确认客户端和服务端都有收发信息的能力,少一次确认不了,多一次浪费资源。

四次挥手

  1. - 第一次挥手:先由客户端向服务器端发送一个 FIN,请求关闭数据传输。
  2. - 第二次挥手:当服务器接收到客户端的 FIN 时,向客户端发送一个 ACK,其中 ack 的值等于 FIN+SEQ
  3. - 第三次挥手:然后服务器向客户端发送一个 FIN,告诉客户端应用程序关闭。
  4. - 第四次挥手:当客户端收到服务器端的 FIN 是,回复一个 ACK 给服务器端。其中 ack 的值等于 FIN+SEQ

网页从开始到加载出来经历了什么

  • - 输入网址之后会做域名解析
  • - 根据 ip 地址查找服务器,开始请求数据
  • - 服务器返回数据,浏览器开始解析
  • - 浏览器再一次请求页面中使用的资源文件
  • - 解析展示整个页面

浏览器渲染引擎的工作原理和工作流程?

1. 解析 HTML 文档,构建 DOM 树(DOM 节点树。

2. 解析 CSS 文档,生成 CSS 规则树。

3. 合并 DOM 树和 CSS 规则树,生成渲染树 render 树。

4. 布局 render 树,计算每个元素的大小,位置等信息(重排会走这一步)。

5. 绘制 render 树,绘制页面的像素信息,(根据 render 树上每个节点的几何属性计算每个节点的像素数,重绘会走这一步)

6. 浏览器会将各层节点的像素信息发给 GPU,GPU 将各层进行合成和渲染,最终展示到页面上。

浏览器安全问题,https 协议,https 与 http 区别

- HTTP 协议工作在 80 端口,HTTPS 协议工作在 443 端口

- HTTPS 需要申请证书(用于验证服务器身份)

- HTTP 在 TCP 三次握手建立连接之后即可开始传输数据;HTTPS 协议则需要在建立 TCP 连接之后客户端与服务器在进行 SSL 加密,确定对话密钥,完成加密后才开始传输数据。

- HTTPS 协议协议:是具有安全性的ssl加密传输协议,为浏览器和服务器之间的通信加密,确保数据传输的安全;

HTTP 协议:是超文本传输协议,信息是明文传输;

HTTP2.0 和 HTTP1.0 的区别

- HTTP2 使用的是二进制传送,HTTP1.X 是文本(字符串)传送

- HTTP2 支持路复用

介绍一下 XSS 攻击和 CSRF?

- XSS(跨站脚本攻击),是一种代码注入攻击,是通过在网站中注入恶意代码达到劫持用户 cookie 或其他信息的一种攻击。

- 客户端:限制输入长度

- 上线前:使用扫描工具自动检测 XSS 漏洞

- CSRF(Cross-site request forgery)跨站请求伪造

- 服务端做一些防御操

跨域

域名协议端口号只要有一个不一致就会引起跨域,跨域是浏览器的安全机制导致的,只有在浏览器中有;

跨域就是通过某些手段来绕过同源策略限制,实现不同服务器之间通信的效果。

跨域如何解决:

1、前端我们解决不了,都是服务器端解决的;

2、在开发的时候:我可以通过配置代理服务器或者浏览器安装插件的方式临时解决,但是上线之后还是需要服务器做配置;

3、通过 jsonp 跨域

jsonp是一种跨域通信的手段,它的原理其实很简单:首先是利用script标签的src属性来实现跨域。通过将前端方法作为参数传递到服务器端,然后由服务器端注入参数之后再返回,实现服务器端向客户端通信。由于使用script标签的src属性,JSONP 使用简单且兼容性不错,但是只限于 get 请求。

4、postMessage 跨域

5、跨域资源共享(CORS)

需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。浏览器会自动进行

CORS 通信,实现 CORS 通信的关键是后端。只要后端实现了 CORS,就实现了跨域。

//谷歌插件 corsf
如果面试官问:“CORS 为什么支持跨域的通信?”
答案:跨域时,浏览器会拦截 Ajax 请求,并在 http 头中加 Origin。

6、nginx 代理跨域

7、nodejs 中间件代理跨域

8、WebSocket 协议跨域

同步和异步

同步叫阻塞模式,异步叫非阻塞模式

异步的实现原理:js 中的事件轮训(eventloop),微任务和宏任务

异步实现的原理:

在js中有一个异步回调队列,当遇到异步任务的时候会把这个任务直接转到异步队列中。等待所有的同步任务都完成之后在执行异步队列
异步队列中的任务会分为微任务和宏任务
每一个宏任务周期中会把当前周期中的所有微任务都执行完成之后,在执行下一个宏任务周期

宏任务:所有的运行环境提供的异步任务
微任务:所有的语言自带的异步任务

什么是异步加载?异步加载和延迟加载有什么区别?

异步加载时相对于同步加载而言的,我们平常书写的代码就是同步加载,代码自上而下执行,是阻塞式的,而异步加载是非阻塞式的,在执行同步代码时,并不会阻塞我后续代码的执行,(例如定时器,发送 ajax 请求),而延迟加载则是一开始并不加载,在我需要的时候再进行加载(例如图片的懒加载)

异步解决方法

(1)回调函数callback

(2)Promise

(3)Generator

(4)async/await

垃圾回收机制

js 会自动的进行垃圾回收,就是那些无用的代码和运行任务会在结束之后从内存中清理出来。js 中的垃圾回收使用的是标记清除法

节流和防抖

防抖:在事件被触发 n 秒后再执行回调,如果在这 n 秒内又被触发,则重新计时(本质是一个定时器)。

例如:搜索框的联想功能,不断输入值的时候,使用防抖来节约资源。(短信验证码、提交表单、resize 事件等)

节流:规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。

例如:scroll 事件,单位时间后计算一次滚动位置,input 事件(上面提到过),播放事件,计算进度条

两者的共同点:

函数防抖和函数节流都是防止某一时间频繁触发,但是这两兄弟之间的原理却不一样。

函数防抖是某一段时间内只执行一次,而函数节流是单位时间执行一次。

回流和重绘

回流一定会触发重绘,但是重绘不一定会引起回流

改变页面布局或者大小尺寸的时候会引起回流,反之就是重绘

重绘:当元素样式的改变不影响布局时,浏览器将使用重绘对元素进行更新 ,UI 层面, 例如改变元素颜色

回流:又叫重排(layout)。当元素的尺寸、结构或者触发某些属性时,浏览器会重新渲染页面,称为回流

Url 从输入到浏览器显示的页面

1. 网络通信

   - 在浏览器中输入 url

   - 应用层 DNS 解析域名

   - 应用层客户端发送 HTTP 请求

   - 传输层 TCP 传输报文

   - 网络层 IP 协议查询 MAC 地址

   - 数据到达数据链路层

   - 服务器接收数据

   - 服务器响应请求

   - 服务器返回相应文件

2. 页面渲染

cookie,localstorage,sessionstorage 的区别?

- cookie:可设置失效时间,没有设置的话,默认是关闭浏览器后失效

- localStorage:除非被手动清除,否则将会永久保存。

- sessionStorage: 仅在当前网页会话下有效,关闭页面或浏览器后就会被清除。同源不共享。

- cookie:4KB 左右 localStorage 和 sessionStorage:可以保存 5MB 的信息。

- cookie:每次都会携带在 HTTP 头中,如果使用 cookie 保存过多- 数据会带来性能问题

- localStorage 和 sessionStorage:仅在客户端(即浏览器)中保存,不参与和服务器的通信

  token 的组成: uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token
  的前几位以哈希算法压缩成的一定长度的十六进制字符串)
  特点:服务端无状态化、可扩展性好支持移动端设备.安全.支持跨程序调用
  每一次请求都需要携带 token,需要把 token 放到 HTTP 的 Header 里
  基于 token 的用户认证是一种服务端无状态的认证方式,服务端不用存放 token 数据。**用解析
  token 的计算时间换取 session 的存储空间,从而减轻服务器的压力,减少频繁的查询数据库**
  token 完全由应用管理,所以它可以避开同源策略

获取用户浏览器信息、浏览器查询

navigator.userAgent  用户代理

获取 url 地址信息并解析 url 参数

location.href

location.search

- 通过字符串截取获取 url 中的参数

 


优化

web 项目性能优化

- 减少 http 请求次数

- 资源文件压缩合并,js 和 css 文件压缩合并

- 使用精灵图片

- 如果图片特别多,使用图片懒加载

- 使用 cdn 的方式加载第三方资源【服务器端运维的范畴】

- 开启 web 服务器的 GZIP 压缩【服务器端运维的范畴】

- CDN

  属于运维的范畴,和前端没有关系。我们以后如果要开启服务器的 CDN 加速,只需要买节点就好

seo 搜索引擎优化

  1. - 为网页添加关键字和描述信息,在 meta 标签中,
  2. - 删除页面中无用的空标签,为图片添加 alt 属性
  3. - 去除不必要的空格, 注释 减少文件的总尺寸,较小的页面可以获得更快的加载速度
  4. - 把 CSS 放在顶端: css 文件的加载不会阻塞 dom 树的解析,把 CSS 文件放在网站的顶端,可以让网站尽可能同时加载其他部件,如图片和文字。
  5. - 设置页面中的 h1-h6 标签 每个页面只出现一个 h1 标签,h2 可以出现多次
  6. - 不定期的更新网站的内容,增加收录量
  7. - 优化网站代码,减少页面加载时间
  8. - 购买外链【花钱】
  9. - 百度竞价排名【花钱】
  10. - 重要内容优先加载
  11. - 语义化 HTML 代码 ,符合 W3C 标准
  12. - 少用 iframe :搜索引擎不会抓取 iframe 中的内容

什么是精灵图片,实现原理是什么?

就是把小图标集中放置在一张图片上,使用背景定位的方式展示每一个小图标

如何实现局部更新?

- ajax,异步的 javascript 和 XML;

- websocket,长连接。建立起链接之后,服务器端可以主动的向客户端推送数据;

网络传输的时候数据安全性如何保障

https,使用 ssl 证书进行加密传输

你做的页面都在哪些浏览器测试过,这些浏览器的内核分别是什么?

- IE 浏览器:Trident 内核

- Chrome 浏览器:webkit(过去)、blink(现在)

- FireFox:Gecko 内核

- Edge:chormium 内核

- Safari:webkit 内核

- 国内主要兼容 360 安全浏览器,极速模式和兼容模式,分别对应谷歌的 blink 内核和 IE 的 trident 内核

- 电脑中浏览器的兼容性(360、qq 浏览器、搜狗)

- 手机浏览器的浏览器兼容性(一般手机,小米手机,ios 手机),微信浏览器。

你是如何解决这些兼容性问题的?

- 答:我们都是浏览器挨个去调试,或者加浏览器前缀,或者 jQuery 来解决 js 的兼容问题,避免使用 h5 和 css3 新增的标签和样式。

tcp 和 udp 的区别

tcp 是面向连接的;udp 不是


第三板块:HTML

块元素

div dl form h1 h2 h3 h4 h5 h6 hr ol li p pre table td tr

行内元素

a b s i u span br img input textarea sub sup

行内元素和块级元素 空元素的特点

行内元素:

        1.无法设置宽高;

        2. 对margin仅设置左右有效,上下无效;

        3. padding上下左右有效;不会自动换行

块级元素:

        1.可以设置宽高

        2. margin和padding的上下左右均对其有效

        3. 超出当前行会自动换行

        4. 多个块状元素标签写在一起,默认排列方式为从上至下

img:属于行内块元素(inline-block),即有行内元素的属性也有块级元素的属性

元素之间的转化可以通过设置样式:display:block/inline/inline-block来改变自身的元素属性

空元素:

       没有闭合标签的标签被称作为空标签。


       在我们使用的标签中,有的具有闭合标签

H5 语义化标签(H5 新增)

- header、nav、footer、main、section、article、address 等等

- 语义化标签就是那些看到单词就知道是做什么的标签,它的优势是便于 seo 优化和可读性更强

多媒体标签(H5 新增特性)

- 如何在网页中添加一个多媒体资源

  audio、video

  我们在实际开发适合可能需要使用到插件:flv.js、video.js、dplayer、hls.js

* 新的表单属性(time、email、url、search)


第四板块:CSS

css3 新增特性

- 阴影:文字阴影 text-shadow 盒子阴影:box-shadow

- 图片背景:background-size background-origin

- 边框:border-radius border-image:CSS3 边框图片

- 伪类(:link,:visited,:active,:hover,:focus,:before,:after)

* 渐变 background-image: linear-gradient(#e66465, #9198e5);

* 过渡 transition: width 2s, height 2s;

* 动画 animation @keyframes

伪类

:checked input:checked 选择所有选中的表单元素
:link a:link 选择所有未访问链接
:visited a:visited 选择所有访问过的链接
:active a:active 选择正在活动链接
:hover a:hover 把鼠标放在链接上的状态
:focus input:focus 选择元素输入后具有焦点
:before p:before 在每个

元素之前插入内容

:after p:after 在每个

元素之后插入内容

媒体查询

  • @media

伪元素

content 属性

选择器 示例 示例说明
:before p:before 在每个

元素之前插入内容

:after p:after 在每个

元素之后插入内容

flex 布局

display:flex;  设置为弹性盒(父元素添加)

flex-direction:row(默认)/column(子元素竖向显示)

justify-content:;  主轴对齐方式()
    fle-start      开头
    flex-end       结尾
    center         居中
    space-around   空间在子元素两边平均分布
    space-between  空间在子元素之间分布
    space-evenly   空间相等

align-items:;    侧轴对齐
    flex-start;
    flex-end;
    center;
    baseline;

flex-wrap:wrap;    换行
align-content:;    多轴对齐
    flex-start      开头
    flex-end        结尾
    center          居中
    space-around    空间在子元素两边空间分布
    space-between   空间在子元素之间分布
    space-evenly    空间相等

常用布局

- 流式布局,盒子自上而下排列。

- 弹性布局,flex 弹性盒。

- grid 网格布局。

- 自适应(响应式布局),使用 rem 单位。

如何实现响应式

媒体查询,@media 作用是设置一个不同的显示范围,在指定的范围中显示我们对应的 css 代码

移动端开发注意事项

1. 页面布局

  •    1) 适配(rem),屏幕特别大的时候字体和页面都会变得很大,显的很奇怪(山寨)。监听window的resize事件,动态改变html标签的字体大小
  •    2) flex+百分比布局(推荐这个)

2. 移动端300ms延迟问题

  •    在移动端中为了解决滑动事件和点击事件
  •    fastclick.js是一个js插件,用来解决这个问题
  •    或者可以使用移动端事件touch,tap

3.一些情况下对非可点击元素如(label,span)监听click事件,ios下不会触发,css增加cursor:pointer就搞定了。

4.CSS动画页面闪白,动画卡顿

   解决方法:

   1.尽可能地使用合成属性transform和opacity来设计CSS3动画,不使用position的left和top来定位

   2.开启硬件加速

  •     -webkit-transform: translate3d(0, 0, 0);
  •     -moz-transform: translate3d(0, 0, 0);
  •     -ms-transform: translate3d(0, 0, 0);
  •     transform: translate3d(0, 0, 0);

rem、em、vw、vh、px、%的关系

px,像素单位

em,相对单位。相对于父节点的字体大小

rem,相对单位。相对于 html 标签的字体大小

vw/vh,是视口单位,1vw=0.01 个视口宽度。默认情况下 1vw=3.75px


禁止用户双指缩放 “maximum-scale”属性的值为“1.0”,“user-scalable”属性的值为“0”
user-scalable:用户是否可以手动缩放
maximum-scale:允许用户缩放到的最大比例。

px 与 rem 的选择?

- 对于只需要适配少部分手机设备,且分辨率对页面影响不大的,使用 px 即可 。

- 对于需要适配各种移动设备,使用 rem,例如只需要适配 iPhone 和 iPad 等分辨率差别比较挺大的设备。

定位方式

absolute:绝对定位。基于离自己最近的一个具有定位属性的父级元素进行定位

relative:相对定位,相对于自身应该出现的位置进行偏移

fixed:固定定位。相对于浏览器窗口进行定位

sticky 粘性定位 基于用户的滚动位置来定位。(一般用于页面导航的吸顶效果)

标准盒模型和怪异盒模型

标准盒模型:标准模式下总宽度=width+margin(左右)+padding(左右)border(左右)

怪异盒模型:怪异模式下总宽度=width+margin(左右)

1. W3C 标准盒模型:

   属性width,height只包含内容content,不包含border和padding。

2. IE (怪异)盒模型:

   属性width,height包含border和padding,指的是content+padding+border。

BFC

块级格式化上下文 一个封闭 的空间  外面的元素不受影响

规则:

  • 1、里面的块上下排列
  • 2、子元素左边距和父元素的左边框相连
  • 3、垂直方向margin叠加
  • 4、一个封闭的空间 外面的元素不受影响
  • 5、BFC不与浮动元素重叠
  • 6、父元素高度计算时,浮动元素参与计算

触发条件:

  • 1、html(根元素)
  • 2、float不为none
  • 3、position为 absolute  fixed
  • 4、display 为inline-block  table-cell  flex
  • 5、overflow 为hidden scroll auto

解决的问题:

  • 1、自适应两栏布局
  • 2、防止margin上下重叠
  • 3、父元素高度计算

高度塌陷

解决方法:

1、为父元素添加overflow:hidden;  缺点:隐藏超出部分

2、在所有浮动起来的元素后面添加空元素块,为空元素添加 clear:both  缺点:容易造成代码冗余.

3、直接给父元素单独设置高度(height);缺点:只适合高度固定的布局,要给出精确的高度,如果高度和父级div不一样时,会产生问题。对于响应式布局会有很大影响。

万能清除法

  div{
​    zoom:1;    兼容ie6 ie7
  }
  div:after{
​    content:"";
​    dispiay:block;
​    clear:both;
​    height:0;
​    visibility:hidden;   将元素隐藏 但空间还在
  }

清除浮动

1.在标签尾部添加空块级标签,设置样式属性为:clear:both;缺点:如果页面浮动布局多,就要增加很多空div,不利于页面的优化。

2. 父级定义伪类after和zoom,.box:after{display:block; clear:both; content:""; visibility:hidden; height:0;}  .box{ zoom: 1 }

3. 简单粗暴,父级设置overflow:hidden,缺点是不能和position配合使用

4. 直接给父元素单独设置高度(height);缺点:只适合高度固定的布局,要给出精确的高度,如果高度和父级div不一样时,会产生问题。对于响应式布局会有很大影响。

水平垂直居中

1、父元素使用 display:flex;

  •   justify-content:center;
  •   align-items:center;

2、定位加位移

  •   子元素 absolute;left: 50%; top: 50%;
  •   transform: translate(-50%, -50%);

3、定位+margin: auto;

  •   position: absolute;
  •   top: 0;
  •   left: 0;
  •   right: 0;
  •   bottom: 0;
  •   margin: auto;

常见浏览器兼容性问题

1、不同浏览器下的padding和margin不同 解决方法:使用通配符(*)将padding和margin设置为0;

2、块属性标签float之后,又有横向的margin值,在IE6中显示会比设置的大(IE6双边距bug) 解决方法:在float标签样式控制中加入display:inline;

3、设置较小的高度标签(一般小于10px),在IE6,IE7,遨游中超出自己设置的高度 解决方法:给超出高度的标签设置overflow:hidden;或者设置行高line-height小于你设置的高度。

4、行内标签设置display:block;后又采用float布局,再设置横向margin值时,在IE6中显示会比设置的大(IE6双边距bug) 解决方法:在display:block;后面加上display:inline;display:table; #滚动条到顶端的距离(滚动高度) var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; #获取非行内样式兼容 IE:currentStyle 标准:getComputedStyle #阻止事件冒泡的兼容 e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true; #获取事件源的兼容 var target = event.target || event.srcElement;

5、图片默认有间距 解决方案:使用float 为img 布局;

6、IE9一下浏览器不能使用opacity 解决方案: opacity: 0.5;filter: alpha(opacity = 50);filter: progid:DXImageTransform.Microsoft.Alpha(style = 0, opacity = 50);

7、边距重叠问题;当相邻两个元素都设置了margin 边距时,margin 将取最大值,舍弃最小值; 解决方案:为了不让边重叠,可以给子元素增加一个父级元素,并设置父级元素为overflow:hidden;

8、cursor:hand 显示手型在safari 上不支持 解决方案:统一使用 cursor:pointer;

9、两个块级元素,父元素设置了overflow:auto;子元素设置了position:relative ;且高度大于父元素,在IE6、IE7会被隐藏而不是溢出; 解决方案:父级元素设置position:relative;

如何实现页面自适应?

- 使用 rem 单位

- 使用媒体查询

- 使用 flex 结合百分比布局

media 属性?screen? All? max-width? min-width?

media: 媒体查询   screen :计算机屏幕    All :默认,适合所有设备

max(min)-width :规定目标显示区域的宽度

css合并写法: @media screen and (min-width:xxxpx) {}

CSS 常见的布局方式?

- 流式布局,盒子自上而下排列。

- 弹性布局,flex 弹性盒。

- grid 网格布局。

- 自适应(响应式布局),使用 rem 单位。

src 和 href 的区别?

- src 是 source 的缩写,表示将外部资源加载到文档内

- href 用于在当前文档和引用资源之间确认联系(侧重点)

- href 会在页面加载时同时加载,src 会在页面加载完加载。

link 和 inport 的区别

(1)@import是 CSS 提供的语法规则,只有导入样式表的作用;link是HTML提供的标签,不仅可以加载 CSS 文件,还可以定义 RSS、rel 连接属性等。

(2)加载页面时,link标签引入的 CSS 被同时加载;@import引入的 CSS 将在页面加载完毕后被加载。

 rgba 和 opacity 的区别

opacity属性的值,可以被它的子元素继承,所有内容透明度都会改变

rgba设置的元素,只对这个元素的背景色有改变,并且,这个元素的后代不会继承这个属性

都有哪些方式实现回到顶部功能?

1. 使用锚点,页面顶部放置一个锚点链接,然后在页面下方放置一个返回到该锚点的链接,用户点击该链接即可返回到该锚点所在的顶部位置。

//锚点方式

    
回到顶部

2. 监听浏览器的 scollTop 事件,当用户滚动到页面底部时,出现回到顶部按钮,点击之后重置浏览器滚动条的高度;

//兼容性获取并监听浏览器滚动条
var osTop=document.documentElement.scrollTop|| document.body.scrollTop;
document.documentElement.scrollTop=document.body.scrollTop = 0;

3.第三方插件,例如 jquery 中:

$("html,body").animate({ srollTop: 0 }, 500);

flex 是如何使用的?

- flex 是一种 css 盒子的布局方式,通过改变父元素的属性来控制子元素的排列方式,其常用属性有:

- flex-direction 主轴的方向

- flex-wrap 子元素空间不足时候是否换行

- justify-content 主轴对齐方式

- align-items 交叉轴的对齐方式

- align-content 多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用

flex:1 代表着什么?

- flex:1 是 flex-grow、flex-shrink、flex-basis 三个属性的缩写,一般默认为 flex:1 1 auto(存在剩余空间就放大,空间不足就缩小);自动填满剩余空间

- flex-grow:元素的放大比例,默认为 1,即使存在剩余空间,也不会放大;

- flex-shrink:元素的缩小比例,默认为 1,即如果空间不足,该元素将缩小;

- flex-basis:项目占据的主轴空间,默认为 auto,即项目原本的大小。

单行或者多行文本溢出展示省略号的实现方法

 

display:none 和 visbility:hidden 的区别

visibility: hidden----将元素隐藏,但是在网页中该占的位置还是占着

display: none----将元素的显示设为无,即在网页中不占任何的位置

 viewport 视口

关于这个问题一定要去搜集一下资料,好好的准备一下

1、 如何设置,都需要设置什么

  content="width=device-width, initial-scale=1.0"

2、如何禁止双指缩放

移动端开发时、给页面头部添加一个meta标签、在标签内添加上 user-scalable = no,initial-scale=1,maximum-scale=1, minimum-scale=1, 四个属性即可(代码如下:

但有一些移动浏览器为了更好的用户体验、并没有遵循这个开发者禁止双指缩放的指定,比如:Safari、UC、QQ浏览器也就是说设置这四个属性已经实现不了这个功能了、这是可以通过 **touchmove** 事件判断多个手指(**touches.length**),并通过阻止事件冒泡 **event.preventDefault()** 来实现 (代码如下:)

  document.documentElement.addEventListener('touchmove', function(event) {
   if (event.touches.length > 1) {
   event.preventDefault();
   }
   }, false);

  但是在我们多次双指操作之后、还是会突破限制按照用户的意愿进行缩放、所以要通过web代码完全实现禁止双指缩放、暂时还不能实现。

移动端 1px 问题

手机设备上看到的 1px 比实际的宽度高 (由于不同的手机有不同的像素密度导致的)

(1)一般是采用伪元素模拟的方式,原理:`把原先元素的 border 去掉,然后利用 :before 或者 :after 重做 border ,并 transform 的 scale 缩小一半,原先的元素相对定位,新做的 border 绝对定位。`

  .scale {
    position: relative;
    border: none;
  }
  .scale:after {
    content: "";
    position: absolute;
    bottom: 0;
    background: #000;
    width: 100%;
    height: 1px;
    transform: scaleY(0.5);
    transform-origin: 0 0;
  }

 (2)可以使用 box-shadow 来模拟边框

position定位以及他们的区别

absolute:绝对定位,基于离自己最近的一个非默认定位的元素进行定位  完全脱离标准文档流

relative:相对定位,相对于自身应该出现的位置进行偏移

fixed:固定定位,针对浏览器进行定位

默认定位,,由左到右,从上往下流式布局

transition 和 animate 的用法以及区别?

 transition 表示过渡,表示一个元素从一种状态到另一种状态所需要的时间;

1. transition 需要事件触发,所以没法在网页加载时自动发生。

2. transition 是一次性的,不能重复发生,除非一再触发。

3. transition 只能定义开始状态和结束状态,不能定义中间状态,也就是说只有两个状态。

animate 表示动画;

 

1. 动画不需要事件触发。

2. 动画可以通过设置 infinite 来循环播放。

3. 可以通过 animation-duration 来设置动画的持续时间,animation-delay 来设置动画开始前的时间等等。

//创建名为myfirst的动画
@keyframes myfirst
{
    from {background: red;}
    to {background: yellow;}
}
//执行动画
keyframes myfirst
{
    from {background: red;}
    to {background: yellow;}
}

如何设置 10px 的字体大小

b{
  font-size .12rem
  font-weight 400
  transform scale(0.8)
}

Sass 和 Less

 Sass和Less都属于CSS预处理器

 Less环境较Sass简单,Less基于JavaScript,Less使用较Sass简单

从功能出发,Sass较Less略强大一些 有函数,变量和作用域

Less与Sass处理机制不一样,前者是通过客户端处理的,后者是通过服务端处理,相比较之下前者解析会比后者慢一点;

脱离文档流三种方法:

float、absolute、fixed

 

 

第五板块:其他

HTML 文件开头的 Doctype 的作用

- 用来声明文档类型,告知浏览器应该以何种规范来解析

- 这叫 W3C 标准,如果不加浏览器会用自己的规范去解析文档,可能在不同浏览器会造成不同的效果

渐进增强和优雅降级如何理解?

- 渐进增强,写样式的时候从低版本的浏览器开始兼容,从下向上兼容。

- 优雅降级,构建页面的时候,先不考虑兼容问题,先构建出完整的页面,再由上向下进行兼容。

什么是组件?什么是模块化?有什么区别?

#组件化

就是基础库或者基础组件,意思是把代码重复的部分提炼出一个个组件供给功能使用

#模块化

就是业务框架或者业务模块,也可以理解为框架,意思是把功能进行划分,将同一类型的代码整合在一起,所以模块的功能相对复杂,都属于同一个业务。

#区别:

使用:组件的使用能在不同项目(模块)重复应用的代码,而模块按照项目功能需求划分成不同类型的业务框架 目的:组件是复用,解耦,模块是为了隔离、封装 依赖:组件之间低依赖,比较独立,模块之间的依赖可通过路由进行耦合 架构定位:组件位于架构底层,被其它层所依赖,模块位于架构业务层

模块化开发

模块化开发:指文件的组织、管理、使用的方式。即把一个大的文件按类型拆分成几个小的文件,他们之间相互引用、依赖

优点:1.可以加速渲染页面,所有资源加载的时间不会因为模块化而加速,但是模块化能加速渲染 2.避免命名冲突 3.代码重用高 4.思路更为清晰,降低代码耦合;

常见排序算法有哪些?

​ 冒泡排序、选择排序、快速排序,二分法排序

浏览器内核常见的有哪些?360 两种模式的内核分别是什么?

ie、火狐、谷歌

360 两种模式,极速和兼容

 

 

 

如有不同见解,欢迎讨论,更多内容,正在更新中。。。。。。

 

 

你可能感兴趣的:(JavaScript,CSS,HTML,面试,前端)