XXXXXX

403 阅读5分钟

一、HTML

1、HTML 语义化

用正确的 HTML 标签来表达正确的意图

语义化元素(具有意义的元素):

  • <header>
  • <nav>
  • <main>
  • <article>
  • <section>
  • <aside>
  • <footer>
  • <figure>
  • <figcaption>
  • ...

语义化元素的优点:

  • 可访问性 —— 机器,搜索引擎,屏幕阅读器等
  • 可读性 —— 人,开发者
  • 一致性 —— 团队

2、meta viewport 的作用

移动端适配

<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">

<meta name="viewport">content 属性:

  • width —— 视口的宽度
  • initial-scale —— 视口的初始缩放比例
  • minimum-scale —— 视口的最小缩放比例
  • maximum-scale —— 视口的最大缩放比例
  • user-scalable —— 是否允许用户缩放

minimum-scalemaximum-scaleuser-scalable 会引起可访问性的问题

二、CSS

1、选择器及优先级

规律:

  • 越具体优先级越高
  • 同样优先级写在后面的覆盖写在前面的
  • !important 优先级最高,但是要少用

优先级:

  1. !important
  2. 内联样式
  3. ID 选择器
  4. 类选择器、属性选择器、伪类
  5. 元素选择器、伪元素

常见的选择器:

/* 奇数 */
li:nth-child(odd) {}

/* 偶数 */
li:nth-child(even) {}

/* 3 的倍数 */
li:nth-child(3n+3) {}

/* 第一个子元素 */
li:first-child {}

/* 最后一个子元素 */
li:last-child {}

/* 不是第一个子元素 */
li:not(:first-child) {}

/* 直接子元素 */
div > p {}

/*
  相邻兄弟元素
  <div>
    <p></p> (×)
    <p></p> (×)
    <img>
    <p></p> (√)
    <p></p> (×)
  </div>
*/
img + p {}

/*
  一般兄弟元素
  <div>
    <p></p> (√)
    <p></p> (√)
    <img>
    <p></p> (√)
    <p></p> (√)
  </div>
*/
img ~ p {}

/*
  伪类
  :first-child
  :last-child
  :hover
  :focus

  伪元素
  ::first-letter
  ::first-line
  ::before
  ::after
*/

2、两种盒模型的区别

标准盒模型:

#box {
  display: content-box;
}

width = content-width

盒子的视觉宽度 = border-left-width + padding-left + width + padding-right + border-right-width

IE 盒模型:

#box {
  display: border-box;
}

width = border-left-width + padding-left + content-width + padding-right + border-right-width

盒子的视觉宽度 = width

3、行内元素和块级元素的区别

行内元素:

inline

  • 不会产生换行
  • widthheight 属性将不起作用
  • 垂直方向的 paddingmarginborder 会被应用,但是不会推开其他行内元素
  • 水平方向的 paddingmarginborder 会被应用,并且会推开其他行内元素
  • 一般情况下,行内元素只能包含数据和其他行内元素

块级元素:

block

  • 会产生换行
  • widthheight 属性可以发挥作用
  • paddingmarginborder 会推开其他元素
  • 一般情况下,块级元素可以包含行内元素和其他块级元素

行内元素和块级元素之间的中间状态:

inline-block

  • 不会产生换行
  • widthheight 属性可以发挥作用
  • paddingmarginborder 会推开其他元素

三、JavaScript

1、JavaScript 有哪些数据类型

基本类型(原始类型、值类型):

  • Undefined
  • Null
  • Boolean
  • Number
  • BigInt
  • String
  • Symbol

对象类型(引用类型):

  • Object

2、如何判断数据类型

(1) typeof 操作符

  • 可以判断出 Null 以外的所有基本类型
  • 无法准确地判断出 Function 以外的所有对象类型
// 基本类型

typeof undefined === 'undefined'

typeof null === 'object' // JavaScript 设计错误

typeof true === 'boolean'

typeof 11 === 'number'

typeof 11n === 'bigint'

typeof 'hello' === 'string'

typeof Symbol('hello') === 'symbol'

// 对象类型

typeof { a: 1 } === 'object'

typeof [1, 2, 3] === 'object'

typeof function () {} === 'function'
typeof class Person {} === 'function'

typeof new Date() === 'object'

typeof /abc/ === 'object'

falsy 值:

  • 0
  • NaN
  • ''
  • null
  • undefined

null 是唯一一个 typeof 返回 'object' 的 falsy 值,所以 ——

const isNull = value => typeof value === 'object' && !value

(2) instanceof 运算符

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

[1, 2, 3] instanceof Array // true
[1, 2, 3] instanceof Object // true

function Person(name, age, gender) {
  this.name = name
  this.age = age
  this.gender = gender
}
const person = new Person('haiyu', 24, 'female')
person instanceof Person // true

// 改变 Person 的原型
Person.prototype = {}
person instanceof Person // false

(3) constructor 属性

constructor 属性返回对实例对象的构造函数的引用

[1, 2, 3].constructor === Array // true

function Person(name, age, gender) {
  this.name = name
  this.age = age
  this.gender = gender
}
const person = new Person('haiyu', 24, 'female')
person.constructor === Person // true

// 改变 person 的构造函数
person.constructor = () => {}
person.constructor === Person // false

(4) Object.prototype.toString 方法

Object.prototype.toString.call(undefined) // '[object Undefined]'

Object.prototype.toString.call(null) // '[object Null]'

Object.prototype.toString.call(true) // '[object Boolean]'

Object.prototype.toString.call(11) // '[object Number]'

Object.prototype.toString.call(11n) // '[object BigInt]'

Object.prototype.toString.call('hello') // '[object String]'

Object.prototype.toString.call(Symbol('hello')) // '[object Symbol]'

Object.prototype.toString.call({ a: 1 }) // '[object Object]'

Object.prototype.toString.call([1, 2, 3]) // '[object Array]'

Object.prototype.toString.call(function () {}) // '[object Function]'
Object.prototype.toString.call(class Person {}) // '[object Function]'

Object.prototype.toString.call(new Date()) // '[object Date]'

Object.prototype.toString.call(/abc/) // '[object RegExp]'

封装一个通用的判断数据类型的方法:

const getType = value => {
  return Object.prototype.toString.call(value)
    .match(/^\[object (\w+)\]$/)[1]
    .toLowerCase()
}

3、判断一个变量是否为整数

Number.isInteger(value)

// Polyfill
Math.floor(value) === value

4、判断数组的方法

Array.isArray 方法:

Array.isArray([1, 2, 3]) // true

instanceof 运算符:

[1, 2, 3] instanceof Array // true

constructor 属性:

[1, 2, 3].constructor === Array // true

Object.prototype.toString 方法:

Object.prototype.toString.call([1, 2, 3]) // '[object Array]'

5、数组的遍历

(1) for

  • 支持 breakcontinue
  • 速度:☆☆☆☆☆
  • 可读性:☆☆☆
const arr = [1, 2, 3]

for (let i = 0, len = arr.length; i < len; i += 1) {
  console.log(arr[i])
}

(2) forEach 方法

  • 不支持 breakcontinue
  • 只能遍历 Array
  • 速度:☆☆☆☆
  • 可读性:☆☆☆☆
const arr = [1, 2, 3]

arr.forEach((item, index, array) => {
  console.log(item)
})

(3) for...of

  • 支持 breakcontinue
  • 支持解构赋值
  • 速度:☆☆☆
  • 可读性:☆☆☆☆☆
const list = [
  {
    name: '秋来也秋去',
    like: 69000,
    creator: '一个人的清欢'
  },
  {
    name: '秋天调色',
    like: 12000,
    creator: '小严同志'
  },
  {
    name: '初恋秋日大片',
    like: 6873,
    creator: '吴莱莱'
  }
]

for (const { name, like, creator } of list) {
  console.log(name, like, creator)
}

其他

  • map
  • every
  • some
  • filter
  • reduce
  • find
  • findIndex
  • ...

6、for...in 和 for...of 的区别

(1) for...in

以任意顺序遍历一个对象(Object)的除 Symbol 以外的可枚举属性(key

Object.prototype.objCustom = () => {}
Array.prototype.arrCustom = () => {}

const list = [1, 2, 3]
list.msg = 'hello'

for (const key in list) {
  console.log(key)
}

// '0'
// '1'
// '2'
// 'msg'
// 'arrCustom'
// 'objCustom'

for (const key in list) {
  if (list.hasOwnProperty(key)) {
    console.log(key)
  }
}

// '0'
// '1'
// '2'
// 'msg'

Object.getOwnPropertyNames(list) // ['0', '1', '2', 'length', 'msg']

Object.defineProperty(list, 'msg', {
  value: 'hello',
  enumerable: false
})

for (const key in list) {
  if (list.hasOwnProperty(key)) {
    console.log(key)
  }
}

// '0'
// '1'
// '2'

(2) for...of

遍历可迭代对象(ArrayStringMapSetargumentsNodeList 等)定义要迭代的数据(item

Object.prototype.objCustom = () => {}
Array.prototype.arrCustom = () => {}

const list = [1, 2, 3]
list.msg = 'hello'

for (const item of list) {
  console.log(item)
}

// 1
// 2
// 3

7、数组的变异方法

会改变原数组的方法:

  • pop:删除最后一个元素
  • push:添加到数组的末尾
  • shift:删除第一个元素
  • unshift:添加到数组的头部
  • reverse:颠倒数组元素的位置
  • sort:原地排序数组元素
  • splice:删除或替换现有元素,或者原地添加新的元素

sort 方法:

默认情况下,元素会按照转换为的字符串的每个字符的 Unicode 位点进行排序

['c', 'b', 'a', 'A'].sort() // ['A', 'a', 'b', 'c']
[1, 2, 3].sort((a, b) => a - b) // [1, 2, 3]
[1, 2, 3].sort((a, b) => b - a) // [3, 2, 1]

8、['1', '3', '10'].map(parseInt)

['1', '3', '10'].map(parseInt)

// parseInt 作为 map 方法的参数 callback
// callback 第一个参数 currentValue,第二个参数 index

[
  parseInt('1', 0),
  parseInt('3', 1),
  parseInt('10', 2)
]

// [1, NaN, 2]

未完待续...