前端笔记

125 阅读15分钟

HTML部分

行内元素有哪些?快级元素有哪些?空元素有哪些?

   行内元素:span img input...
   块级元素: div footer header section p h1...h6
   空元素:br hr
   元素之间的转换问题:
   display: inline;   把某元素转换成了行内元素
   display: inline-block;   把某元素转换成了行内块元素
   display: block;     把某元素转换成了块元素

页面导入样式时,使用link和@import有什么区别?

区别1: link先有,后有@import(兼容性link比@import好)
区别2: 加载顺序差别,浏览器先加载标签link, 后加载@import

title与h1的区别、b与strong的区别、i与em的区别?

titleh1的区别:
定义:title:概括了网站信息,可以告诉搜索引擎或用户关于这个网站的内容主题是什么
     h1: 文章主题内容,告诉浏览器我们的网站内容主要是什么
区别:title是显示在网页标题上、h1是显示在网页内容上
     titleh1添加的重要(title > h1)----对于seo的了解
场景:网站的logo都是用h1标签包裹的

bstrong的区别
定义:b: 实体标签,用来给文字加粗的,strong:逻辑标签,用来加粗字符语气的
区别:b标签只有加粗的样式,没有实际含义,strong表示标签内字符比较重要,用以强调的。
为了符合css3的规范,b尽量少用,用strong就可以了

iem的区别
定义:i:实体标签,用来做文字倾斜的,em:逻辑标签,用来强调文字内容的
区别:i只是一个倾斜标签,没有实际含义,em表示标签内字符重要,用以强调的
场景:i更多的用在自图图标上,em用在术语上(医药,生物)

img标签的title和alt有什么区别?

title: 鼠标移入到图片显示的值,alt: 图片无法加载时显示的值
在seo的层面上,蜘蛛抓取不到图片的内容,所以前端在写img标签的时候为了增加seo效果要加入
alt数学来描述这张图是什么内容或者关键字

png、jpg、gif这些图片格式解释一下?分别什么时候用?

png: 无损压缩,尺寸体积要比jpg/jpeg的大,适合做小图标
jpg: 采用压缩算法,有一点失真,比png体积要小,适合做重大图标
gif: 一般是做动图的
webp: 同时支持有损或者无损压缩,相同质量的图片,webp具有更小的体积,兼容性不是特别好。

CSS部分

介绍一下css的盒模型

css的盒子模型有哪些:标准盒模型,IE盒模型
区别:标准盒子模型:marginborderpaddingcontent
     IE盒子模型:margincontent(border+padding+content)
通过css如何转换盒子模型
     box-sizing: content-box;
     box-sizing: border-box;

line-height和height的区别

line-height: 是每一行文字的高,如果文字换行则整个盒子高度会增大(行数*高度)
height: 是一个死值,则是这个盒子的高度

css选择符有哪些?哪些属性可以继承?

css选择器:通配(*)
          id选择器(#)
          类选择器(.)
          标签选择器(div p h1...)
          相邻选择器(+)
          后代选择器(ul li)
          子元素选择器(>)
          属性选择器(a[href])
css属性哪些可以继承:文字系列:font-size color line-height text-align
不可继承属性:border padding margin...
       

用css画一个三角形

.box{ 
    width: 0px;
    height: 0px;
    border: 100px solid;
    border-top-color: red;
    border-right-color: transparent;
    border-bottom-color: transparent;
    border-left-color: transparent;
 }

一个盒子不给宽度和高度如何水平垂直居中?

方式一

  <div class="container">
    <div class="main">main</div>
  </div>
  .container{
      display: flex;
      justify-content: center;
      align-items: center;
      height: 300px;
      width: 300px;
      border: 5px solid #ddd;
    }
    .main{
      background: red;
    }

方式二

.container{
  position: relative;
  height: 300px;
  width: 300px;
  border: 5px solid #ddd;
}
.main{
  background: red;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

方式三

.container{
  display: flex;
  height: 300px;
  width: 300px;
  border: 5px solid #ddd;
}
.main{
  background: red;
  margin: auto;
}

display有哪些值,说明它们的作用

none:隐藏元素
block:把某元素转换成块元素
inline:把某元素转换成内联元素
inline-block:把某元素转换成行内块元素

对BFC规范的理解?

BFC就是页面上一个隔离的独立容器,容器里的子元素不会影响到外面的元素
BFC:块级格式化上下文
BFC的原则: 如果一个元素具有BFC, 那么内部元素再怎么弄,都不会影响到外面的元素
如何触发BFC: 
    float的值非none
    overflow的值非visib
    display的值为:inline-block,table-cell...
    position的值为:absolute,fixed

清除浮动有哪些方式?

1, 触发BFC
2, 多创建一个盒子,添加样式:clear: both
3, after方式
ul:afetr{
    content: '';
    display: block;
    clear: both;
 }

在网页中应该使用奇数还是偶数字体?为什么?

偶数

position有哪些值?分别是根据什么定位的?

static: 没有定位,默认
fixed: 固定定位,相对于浏览器窗口进行定位
relative: 相对于自身定位,不脱离文档流
absolute: 相对于第一个有relative的父元素定位,脱离文档流

relative和absolute区别
relative不脱离文档流,absolute脱离文档流
relative相对于自身,absolute相对于第一个有relative的父元素
relative如果有left, right, top, bottom => left, top
absolute如果有left, right, top, bottom => left, right, top, bottom

写一个左中右布局占满屏幕,其中左右两块固定宽200,中间自适应,要求先加载中间块

双飞翼布局

<div class="container">
    <div class="c">
      <div class="main">中</div>
    </div>
    <div class="l">左</div>
    <div class="r">右</div>
</div>

*{margin: 0; padding: 0}
    body{
      width: 100vw;
      height: 100vh;
    }
    .container > div{
      float: left;
    }
    .l{
      margin-left: -100%;
      width: 200px;
      height: 100vh;
      background: green;
    }
    .c{
      width: 100%;
      background: pink;
      height: 100vh;
    }
    .r{
      margin-left: -200px;
      width: 200px;
      height: 100vh;
      background: yellow;
    }
    .main{
      padding: 0 200px;
    }

display:none与visiblity:hidden的区别

1,占用位置的区别: display: none, 不占位置
                 visibility: hidden, 虽然隐藏了,但是占用位置
2, 重绘和回流的问题: visibility: hidden; display: none; 产生重绘
                  display: none; 还会产生一次回流
产生回流一定会造成重绘,但是重绘不一定会造成回流
产生回流的情况:改变元素的位置(left, top...) 显示隐藏元素...
产生重绘的情况:样式改变(background, color...)

css sprite是什么,有什么优缺点

css sprite:把多个小图标合成一张大图
优缺点:优点:减少了http请求的次数,提升了性能
       缺点:维护比较差(例如图片位置进行修改或者内容宽高修改)

opacity和rgba区别

共同性:实现透明效果
1opacity 取值范围01之间,0表示完全透明,1表示不透明
1,rgba R表示红色,G表示绿色,B表示蓝色,取值可以在正整数或者百分数,A表示透明度取值01之间
区别:继承的区别,opacity会继承父元素的opacity属性,而rgba设置的元素的后代元素不会继承不透明属性

JavaScript部分

延迟加载JS有哪些方式

延迟加载:async defer
<script defer type="text/javascript" src="script.js"></script>
defer: 等html全部解析完成,才会执行js代码,顺次执行js脚本
async: async是和html解析同步的(一起的),不是顺次执行js脚本(谁先加载完谁先执行)

js数据类型

基本类型:string number boolean undefined null symbol bigint
引用类型:object
NaN是一个数值类型,但不是一个具体的数字

null undefined区别

区别:null是一个表示"无"的对象(空对象指针),转为数值时为0undefined是一个表示"无"的原始值,转为数值时为NaN

JS微任务和宏任务

1, js是单线程语言
2, js代码执行流程:同步执行完 ==》事件循环
    同步的任务都执行完了,才会执行事件循环的内容
    进入事件循环:请求、定时器、事件...
3, 事件循环中包含:微任务 宏任务
    微任务: promise.then
    宏任务: setTimeout...
要执行宏任务的前提是清空了所有的微任务
流程: 同步 --》事件循环【微任务 宏任务】 --》微任务 --》宏任务 --》微任务...

js作用域考题

1,除了函数外,js是没有块级作用域的
2,作用域链:内部可以访问外部的变量,但是外部不能访问内部的变量
    注意:如果内部有,优先查找内部,如果内部没有就查找外部的
3,注意声明变量是用var还是没有写(window.)
4,注意:js有变量提升的机制
5,优先级:声明变量 > 声明普通函数 > 参数 > 变量提升(普通声明函数是不看写函数的时候顺序)

考题一
function c() {
    var b = 1;
    function a() {
      console.log(b)
      var b = 2;
      console.log(b)
    }
    a()
    console.log(b)
}
c()

考题二
var name = 'a';
  (function() {
    if(typeof name == 'undefined') {
      var name = 'b'
      console.log('111' + name)
    } else {
      console.log('222' + name)
    }
  })()
  
考题三
function fun(a) {
    var a = 10;
    function a(){}
    console.log(a)
  }
  fun(100)

JS面向对象考题

1,对象是通过new操作符构建出来的,所以对象之间不相等(除了引用外)
2,对象注意:引用类型(共同一个地址)
3,对象的key值都是字符串类型
4,对象如何找属性|方法:
    先在对象本身找 --> 构造函数中找 --> 对象原型中找 --> 构造函数原型中找
    --> 对象上一层原型中找
function Fun() {
  this.a = '在Fun函数中添加的'
}
Fun.prototype.a = '这是Fun原型添加的'
let obj = new Fun()
obj.a = '对象本身添加的'
obj.__proto__.a = '这是对象原型添加的'
Object.prototype.a = '这是Object原型添加的'
console.log(obj.a)

JS作用域+this指向+原型考题

考题1

var o = {
  a: 10,
  b: {
    a: 2,
    fn: function() {
      console.log(this.a) // 2
      console.log(this) // 代表b
    }
  }
}
o.b.fn()

考题2

window.name = 'Stoney'
function A() {
  this.name = 123;
}
A.prototype.getA = function() {
  console.log(this)
  return this.name + 1
}
let a = new A;
let funcA = a.getA;
console.log(funcA())

考题3

var length = 10
function fn() {
  return this.length + 1
}
var obj = {
  length: 5,
  test1: function() {
    return fn()
  }
}
obj.test2 = fn
console.log(obj.test1())
console.log(fn() === obj.test2())
console.log(fn(), obj.test2())
console.log(obj.test1() == obj.test2())
console.log(obj.test1(), obj.test2())

考题4

function Foo() {
  getName = function() {console.log(1)}
  return this
}
Foo.getName = function() {console.log(2)}
Foo.prototype.getName = function(){console.log(3)}
var getName = function(){console.log(4)}
function getName() {
  console.log(5)
}
Foo.getName() // 2
getName() // 4
Foo().getName() // 1
getName() // 1
new Foo().getName() // 3

考题5

var fullName = 'language'
var obj = {
    fullName: 'javascript',
    prop: {
        getFullName: function() {
            return this.fullName
        }
    }
}
console.log(obj.prop.getFullName()) // undefined
var test = obj.prop.getFullName
console.log(test()); // language

考题6

var age = 20
function test() {
    console.log(this.age)
}
let obj = {age: 30}
obj.test = test
obj.test() // 30

考题7

var age = 20
let obj = {age: 30}
obj.test = function() {
    return function() {
        console.log(this.age)
    }
}
obj.test()(); // 20

考题8

var name = 'window'
var Tom = {
  name: 'tom',
  show: function() {
    console.log(this.name)
  },
  wait: function() {
    var fun = this.show
    fun()
  }
}
Tom.wait() // window

考题9

ar name = 'window'
var Tom = {
  name: 'tom',
  show: function() {
    console.log(this.name)
  },
  wait: function() {
    var fun = this.show
    fun()
    this.show()
  }
}
Tom.wait()
// window
// tom

JS判断变量是不是数组,你能写出哪些方法

Array.isArray()
arr instanceof Array
Object.prototype.toString.call(arr).indexOf('Array') > -1
Array.prototype.isPrototypeOf(arr)
arr.constructor.toString().indexOf('Array') > -1

slice是干嘛的,splice是否会改变原数组

1, slice是来截取数组的,返回的是一个新数组
2, splice 功能有:插入、删除、替换
    返回: 删除的元素,该方法会改变原数组

找出多维数组最大值

function fnArr(arr) {
  let newArr = []
  arr.forEach((item, index) => {
    newArr.push(Math.max(...item))
  })
  return newArr
}
console.log(fnArr([
  [4, 5, 1, 3],
  [13, 27, 18, 26],
  [32, 35, 37, 39],
  [1000, 1233, 865, 1]
]))

给字符串新增方法实现功能

String.prototype.addPrefix = function(str) {
  return str + this;
}
console.log('world'.addPrefix('hello '))

找出字符串出现次数最多的字符以及次数

function getMaxCode(str) {
  let maxCode = {count: 0, code: ''}
  let obj = {}
  for (let i = 0; i < str.length; i++) {
    let code = str[i]
    if(!obj[code]) obj[code] = 1
    else obj[code]++
    if(obj[code] > maxCode.count) {
      maxCode = {code, count: obj[code]}
    }
  }
  return maxCode
}
console.log(getMaxCode('wwwwwwuwhciubci'))

new操作符具体做了什么

1, 创建了一个空对象
2, 将空对象的原型,指向于构造函数的原型
3, 将空对象作为构造函数的上下文(改变this指向)
4, 对构造函数有返回值的处理判断

实现:

function Fun(age, name) {
  this.age = age
  this.name = name
}
function create(fn, ...args) {
  var obj = {}
  Object.setPrototypeOf(obj, fn.prototype)
  var result = fn.apply(obj, args)
  return result instanceof Object ? result : obj
}
console.log(create(Fun, 18, 'stoney'))

闭包

1, 闭包是一个函数加上到创建函数的作用域的连接,闭包"关闭"了函数的自由变量
2, 闭包可以解决什么问题
    2.1, 内部函数可以访问到外部函数的局部变量
    2.2, 闭包可以解决的问题
    var lis = document.getElementsByTagName('li')
    for (var i = 0; i < lis.length; i++) {
      (function(i) {
        lis[i].onclick = function() {
          alert(i)
        }
      })(i)
    }
3, 闭包的缺点:
    3.1, 变量会驻留在内存中,造成性能损耗的问题
        解决:把闭包的函数设置为null
        var lis = document.getElementsByTagName('li')
        for (var i = 0; i < lis.length; i++) {
          (function(i) {
            lis[i].onclick = function() {
              alert(i)
            }
            lis[i] = null
          })(i)
        }

JS原型链

1, 原型可以解决的问题:对象共享属性和共享方法
2, 谁有原型:函数拥有:prototype 对象拥有:__proto__
3, 对象查找属性或者方法顺序
先在对象本身中查找 --> 构造函数中查找 --> 对象的原型 --> 构造函数的原型中 --> 当前原型的原型中查找
4, 原型链
    原型链就是把原型串联起来
    原型链的最顶端是null

JS的继承方式

es6继承

class Parent{
  constructor() {
    this.age = 18;
  }
}
class Child extends Parent{
  constructor() {
    super()
    this.name = 'stoney'
  }
}
let o1 = new Child()
console.log(o1, o1.name, o1.age)

原型链继承

function Parent() {
  this.age = 20
}
function Child() {
  this.name = 'Stoney'
}
Child.prototype = new Parent()
let o2 = new Child()
console.log(o2, o2.name, o2.age)

借用构造函数继承

function Parent() {
  this.age = 22
}
function Child() {
  this.name = 'stoney'
  Parent.call(this)
}
let o3 = new Child()
console.log(o3, o3.name, o3.age)

组合式继承

function Parent() {
  this.age = 22
}
function Child() {
  Parent.call(this)
  this.name = 'stoney'
}
Child.prototype = new Parent()
let o4 = new Child()
console.log(o4, o4.name, o4.age)

说一下call、apply、bind的区别

共同点

可以改变this指向,语法:函数.call()、函数.apply()、函数.bind()

区别

1, call、apply可以立即执行。bind不会立即执行,因为bind返回的是一个函数需要加入()执行
2, 参数不同:apply第二个参数是数组。call和bind有多个参数需要挨个写

场景

1, 用apply的情况
var arr1 = [1, 2, 443, 3, 5]
console.log(Math.max.apply(null, arr1))
2, 用bind的情况
<button id='btn'>1111</button>
<h1 id='hls'>2222</h1>

var btn = document.getElementById('btn')
var hls = document.getElementById('hls')
btn.onclick = function() {
  console.log(this.id)
}.bind(hls)

深拷贝和浅拷贝

浅拷贝:
创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,
如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
深拷贝:
将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象
实现:
JSON.parse(JSON.stringify())
递归实现
function copyObj(obj) {
  if(Array.isArray(obj)) {
    var newObj = []
  } else {
    var newObj = {}
  }
  for (var key in obj) {
    if(typeof obj[key] == 'object') {
      newObj[key] = copyObj(obj[key])
    } else {
      newObj[key] = obj[key]
    }
  }
  return newObj
}
var obj1 = {
  a: 1,
  b:2,
  arr: [1, 3, 44, 55]
}
var obj2 = copyObj(obj1)
obj2.arr.push(54)
console.log(obj1, obj2)

localstorage、sessionstorage、cookie的区别

公共点:在客户端存放数据
区别:
1, 数据存放有效期
    sessionstorage:仅在当前浏览器窗口关闭之前有效(关闭浏览器就没了)
    localstorage:始终有效,窗口或浏览器关闭也一直保存,所以叫持久化存储
    cookie:只在设置的cookie过期时间之前有效,即使窗口或浏览器关闭也有效
2, localstorage、sessionstorage不可以设置过期时间
    cookie 有过期时间,可以设置过期(把时间调整到之前的时间,就过期了)
3, 存储大小的限制
    cookie存储量不能超过4K
    localstorage、sessionstorage不能超过5M
    根据不同的浏览器存储的大小是不同的

H5/CSS3部分

什么是语义化标签

1, 易读性和维护性更好
2, seo成分会更好,蜘蛛抓取更好
3, IE8不兼容HTML5标签。解决:可以通过html5shiv.js去处理

如何关闭iOS键盘首字母自动大写

<input type="text" autocapitalize='off'>

怎么让Chrome支持小于12px的文字

Chrome默认字体大小是16px, 每个浏览器默认字体大小可能不一样
div span {
    display: inline-block;
    -webkit-transform: scale(0.8);
}

rem和em区别

相对于font-size
em相对于父元素的font-size
rem相对于根html元素的font-size

iOS系统中元素被触摸时产生的半透明灰色遮罩怎么去掉

a, button, input, textarea{
    -webkit-tap-highlight-color: ragba(0,0,0,0)
}

webkit表单输入框placeholder的颜色值能改吗

input::-webkit-input-placeholder{
    color: red;
}

禁止iOS长按时不触发系统的菜单,禁止iOS/android长按时下载图片

html, body{
    touch-callout: none;
    -webkit-touch-callout: none;
    
    user-select: none;
    -webkit-user-select: none;   
}

禁止iOS和andro用户选文字

{
 user-select: none;
 -webkit-user-select: none; 
}

自适应

淘宝无限适配【移动端】:淘宝无限适配 + 布局单位使用rem
function flexible() {
    let dom = document.documentElement;
    let w = doc.clientWidth / 10;
    dom.style.fontSize = w + 'px';
 }
 flexible();
 window.onresize = function() {
     flexible();
 }

响应式

响应式:一个url可以响应多端
语法结构
@media only screen and (max-width: 1000px) {
    ul li:last-child{
        display: none;
    }
 }
 only: 可以排除不支持媒体查询的浏览器
 screen: 设备类型
 max-width | max-height | min-width | max-height
 响应式图片【性能优化】
 <picture>
     <source srcset="1.jpg" media='(min-width: 1000px)' />
     <source srcset="2.jpg" media='(min-width: 700px)' />
     <img srcset = '3.jpg' >
 </picture>

ES6相关

var、let、const的区别

varletconst共同点都是可以声明变量的
区别一:var 具有变量提升的机制,letconst没有变量提升的机制
区别二:var 可以多次声明同一个变量,letconst不可以多次声明同一个变量
区别三:varlet声明变量 const 声明常量,varlet声明的变量可以再次赋值,
        但是const不可以再次赋值了
区别四:var声明的变量没有自身作用域的,letconst声明的变量具有自身的作用域

对象合并

方式一:Object.assign

const a = {a: 1, b: 4}
const b = {b: 2, c: 3}
let obj1 = Object.assign(a, b)
console.log(obj1)

方式二...

const a = {a: 1, b: 4}
const b = {b: 2, c: 3}
let obj2 = {...a, ...b}
console.log(obj2)

方式三

const a = {a: 1, b: 4}
const b = {b: 2, c: 3}
function extend(target, source) {
  for(var obj in source) {
    target[obj] = source[obj]
  }
  return target
}
console.log(extend(a, b))

Promise

用Promise对fetchData进行包装,将回调的设计封装成then的形式

function fetchData(callback) {
    setTimeout(() => {
        callback('this. is data return')
    }, 5000)
}
// 实现下面的函数
function promiseFetch() {
// 你的代码
}

实现如下

function fetchData(callback) {
    setTimeout(() => {
        callback('this. is data return')
    }, 5000)
}

function promiseFetch() {
    return new Promise((resolve) => {
        fetchData(resolve)
    })
}
promiseFetch().then(res => {
    console.log(res)
})

给出如下地址数据格式,实现函数getNameById, 输入address, id,输出id对应的地址name

const address = [
  {
    id: 1,
    name: '北京市',
    children: [
      {
        id: 11,
        name: '海淀区',
        children: [
          {
              id: 111,
              name: '中关村'
          }
        ]
      }, {
        id: 12,
        name: '朝阳区'
      }
    ]
  }, {
    id: 2,
    name: '天津市'
  }
]
// 请实现该函数
// 输入: getNameById(address, 2) 输出:‘天津市’
// 输入: getNameById(address, 111) 输出:‘中关村’
// 输入: getNameById(address, 32) 输出:‘’
function getNameById(address, id) {
  
}

实现

function getNameById(address, id) {
  const list = tree2List(address)
  const result = list.find(item => item.id === id)
  return result ? result.name : ''
}

function tree2List(tree) {
  return tree.reduce((accu, item) => {
    if(!item.children) {
      accu.push(item)
    } else {
      const subList = tree2List(item.children)
      accu.push(item, ...subList)
    }
    return accu
  }, [])
}