JavaScript 篇

1. 数据类型检测的方式有哪些

(1) typeof

console.log(typeof 2);               // number
console.log(typeof true);            // boolean
console.log(typeof 'str');           // string
console.log(typeof []);              // object
console.log(typeof function(){
   });    // function
console.log(typeof {
   });              // object
console.log(typeof undefined);       // undefined
console.log(typeof null);            // object

(2)instanceof
instanceof可以正确判断对象的类型,其内部运行机制是判断在其原型链中能否找到该类型的原型

console.log(2 instanceof Number);                    // false
console.log(true instanceof Boolean);                // false 
console.log('str' instanceof String);                // false 
 
console.log([] instanceof Array);                    // true
console.log([] instanceof Object);                   // true
console.log(Array instanceof Object);                // true
console.log(function(){
   } instanceof Function);       // true
console.log({
   } instanceof Object);                   // true

instanceof只能正确判断引用数据类型,而不能判断基本数据类型。

(3)constructor

console.log((2).constructor === Number);    // true
console.log((true).constructor === Boolean); // true
console.log(('str').constructor === String); // true
console.log(([]).constructor === Array); // true
console.log((function() {
   }).constructor === Function); // true
console.log(({
   }).constructor === Object); // true

constructor 有两个作用,一个是判断数据的类型,二是对象实例通过constructor对象访问它的构造函数

2. typeof null 的结果是什么,为什么?

typeof null 的结果是Object

在JavaScript 第一个版本中,所有值存储在32位的单元中,每个单元包含一个小的类型标签(1-3 bits)以及当前要存储值的真实数据。

000:object   - 当前存储的数据指向一个对象
  1:int      - 当前存储的数据是一个31位的有符号整数
010:double   - 当前存储的数据指向一个双精度的浮点数
100:string   - 当前存储的数据指向一个字符串
110:boolean  - 当前存储的数据是布尔值

null 的值是机器吗NULL指针(null指针的值全是0),
所以说null的类型标签也是000,和Object的类型标签一样,所以会被判定为Object

3. 其他值到布尔值的转换规则?

以下这些值是假值

undefined
null
false
0
NaN

这些假值布尔强制类型转换结果为false,从逻辑上说,假值列表以外的都应该是真值

5. || 和 && 操作符的返回值

|| 和 && 首先会对第一个操作数进行条件判断,如果其不是布尔值就先强制转换为布尔类型,然后再执行条件判断

  • 对于| | 来说,如果条件判断为true就返回第一个操作数的值,如果为false就返回第二个操作数的值
  • && 则相反,如果条件判断结果为true就返回第二个操作数的值,如果为false 就返回第一个操作数的值

| | 和 && 返回它们其中一个操作数的值,而非条件判断的结果

实例

console.log(1 || 3);  // 1
console.log(1 && 3);  // 3

console.log(null || 'str'); // 'str'
console.log(null && 'str'); // null

当操作符两边皆为boolean类型时,才会返回boolean类型
console.log(false || true);  // true
console.log(false && true);  // false

6. 如何提取高度嵌套的对象里的指定属性?

嵌套程度非常深的对象:

const school = {
   
  classes: {
   
    stu: {
   
      name: 'Bob',
      age: 24
    }
  }
}

标准的结构做法

const {
   classes: {
   stu: {
    name }}} = school
console.log(name)  // 'Bob'

7. 什么是DOM和BOM

  • DOM 指的是文档对象模型,它指的是把文档当做一个对象,这个对象主要定义了处理页面内容的方法和接口
  • BOM 指的是浏览器对象模型,它指的是把浏览器当做一个对象来对待,这对象主要定义了与浏览器进行交互的方法和接口

8. for…in 和 for…of 的区别

for…of 是ES6新增的遍历方式,允许遍历一个含有iterator 接口的数据结构(数组、对象等)并且返回各项的值,不支持遍历普通对象(会报错),因为没有迭代器对象,和ES3 中的for…in 的区别如下

  • for…of 遍历获取的是对象的键值,for…in 获取的是对象的键名
let obj = ['a', 'b', 'c']

let obj2 = [...obj]  //{0: "a",1: "b",2: "c"}
for(let item in obj) {
   
   console.log(item)
} // 0 1 2
for(let item of obj) {
   
   console.log(item)
} // a b c
  • for…in 会遍历对象的整个原型链,性能非常差不推荐使用,而for…of 只遍历当前对象不会遍历原型链
  • 对于数组的遍历,for…in 会返回数组中所有可枚举的属性(包括原型链上可枚举的属性),for…of 只返回数组的下标对应的属性值

总结: for…in 循环主要是为了遍历对象而生,不适用与遍历对象;
for…of 循环可以用来遍历数组、类数组对象,字符串、Set、Map以及Genertate对象

9. 常见的位运算符有哪些?

常见的位运算符有以下几种:

运算符 描述 运算规则
& 两个位都为1时,结果才为1
| 有一位为1时,结果就为1
^ 异或 两个位相同为0,相异为1
~ 取反 0 变 1,1 变 0
<< 左移 各二进制位全部左移若干位,高位丢弃,低位补位
>> 右移 各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃

1. 按位与运算符(&)
定义: 参加运算的两个数组按二进制位进行“与”运算
运算规则:

0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

总结:两位同时为 1,结果才为1,否则为0

实例

    /* * 0000 0011 | 0000 0101 = 0000 0001 两位都为1则为1 */
    console.log(3 & 5); //1
    /* 1000 0011 1000 0101 负数进行位运算先取补码 1111 1101 1111 1011 | 1111 1001 结果为负数,需取补码 1000 0111 */
    console.log(-3 & -5);  // -7

2. 按位或运算符(|)
定义: 参加运算的两个对象按二进制进行“或”运算
运算规则:

0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1

总结:参加运算的两个对象只要有一个为1,其值为1。
实例

    /* * 0000 0011 | 0000 0101 = 0000 0111 两位有一位为1则为1 */
    console.log(3 | 5); //7
    /* 1000 0011 1000 0101 负数进行位运算先取补码 1111 1101 1111 1011 | 1111 1111 结果为负数,需取补码 1000 0001 */
    console.log(-3 | -5);  // -1
    

3. 异或运算符(^)
定义: 参加运算的两个数据按二进制位进行“异或”运算。
运算规则:

0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 0
1 ^ 1 = 0

总结: 参加运算的两个对象,如果两个相应位相同为0,相异为1

实例

/** * 0000 0101 * ^ 0000 1001 * = 0000 1100 两位相同为0,不同为1 **/
    console.log(5^9); // 12
    /* * 1000 0101 ^ 1000 1001 负数先取补码,再进行运算 1111 1011 ^ 1111 0111 = 0000 1100 */
    console.log(-5^-9);  // 12

4. 取反运算符(~)
定义: 参加运算的一个数据按二进制进行“取反”运算
运算规则:

~ 1 = 0 ; ~ 0 = 1

总结: 对一个二进制数按位取反,即将0变成1,1变成0.
实例

    /* * 1000 1000 => 1111 1000 负数运算,需要先取其补码 => 1000 0111 取反,为正数则为其原码 */
    console.log(~-8); //7
    /* 0000 1000 * => 1111 0111 先取反 * => 1000 1001 若取反为负数,则取其补码 */
    console.log(~8);  // -9

5. 左移运算符(<<)
定义: 将运算对象各二进制位全部左移若干位
左边溢出位丢弃,右边空出位补0
实例

    // 0000 0011 => 0000 1100 各二进制位项左移2位
    console.log(3<<2);
    /* 1000 0011 => 1111 1101 负数运算先取补码 => 1111 0100 => 1000 1100 结果为负数再取补码 */
     console.log(-3<<2);  // -12
  1. 右移运算符
    定义:将运算对象的各二进制位全部右移若干位
    正数左边空余位补0,负数左边空余位补1;右边溢出位舍弃
    实例:
    // 0000 0011 => 0000 0000 各二进制位项右移3位
    console.log(3>>3); // 0
    /* 1000 0011 => 1111 1101 负数运算先取补码 => 1111 1111 => 1000 0001 结果为负数再取补码 */
     console.log(-3>>3);  // -1
  1. 原码、反码和补码
    上面提到了补码、反码等知识,这里就补充一下。 计算机中的有符号数有三种表示方法,即原码、反码和补码。三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位,三种表示方法各不相同。
    (1)原码
    原码就是一个数的二进制数。例如:10的原码为0000 1010
    (2)反码
  • 正数的反码与原码相同,如:10 反码为 0000 1010
  • 负数的反码为除符号位,按位取反,即0变1,1变0。
    例如:-10
原码:1000 1010
反码:1111 0101

(3)补码

  • 正数的补码与原码相同,如:10 补码为 0000 1010
  • 负数的补码是原码除符号位外的所有位取反即0变1,1变0,然后加1,也就是反码加1。
    例如: -10
原码:1000 1010
反码:1111 0101
补码:1111 0110

HTML

1. src 和 href 的区别

src 和 href 都是用来引用外部的资源,它们的区别如下:

  • src: 表示对资源的引用,它指向的内容会嵌入到当前标签所在的位置。
  • href 表示超文本引用,它指向一些网络资源,建立和当前元素或本文档的链接关系。

2. 对HTML语义化的理解

语义化是指根据内容的结构化(内容语义化),选择合适的标签(代码语义化)。通俗来讲就是用正确的标签做正确的事情。
语义化的优点:

  • 对机器友好,带有语义的文字表现力丰富,更适合搜索引擎的爬虫爬取有效信息
  • 对开发者友好,使用语义类标签增强了可读性,结构更加清晰,开发者能清晰的看出网页的结构,便于团队的开发与维护。

常见的语义化标签:

< header>< /header> 头部
< nav>< /nav> 导航栏
< section>< /section> 区块(有语义化的div)
< main>< /main> 主要区域

CSS

1. link 和 @import 的区别

两者都是外部引用CSS的方法,它们的区别如下:

  • link是XHTML标签,除了加载CSS外,还可以定义RSS等其他事务;@import属于CSS范畴,只能加载CSS
  • link引用CSS时,在页面载入时同时加载;@import 需要页面网页完全载入以后加载
  • link是XHTML 标签,无兼容问题;@import 是在CSS2.1提出的,低版本的浏览器不支持
  • link 支持使用JavaScript控制DOM去改变样式;而@import不支持

2. 伪元素和伪类的区别和作用?

  • 伪元素: 在内容元素的前后插入额外的元素和样式,但是这些元素实际上并不在文档中生产层。它们只在外部显示课件,但不会在文档的源代码中找到它们,因此,称为“伪”元素

p::before {content: "第一章“;}
p::after { content: “Hot!”;}

  • 伪类: 将特殊的效果添加到特定选择器上。它是已有元素上添加类别,不会产生新的元素

a:hover {color: #FF00FF}
p:first-child { color: red }

总结: 伪类是通过在元素选择器上加入伪类改变元素状态,而伪元素通过对元素的操作进行对元素的改变

3. 对BFC的理解,如何创建BFC

先看两个相关的概念:

  • Box: Box 是CSS布局的对象和基本单位,一个页面是由多个Box组成的,这个Box就是我们所说的盒模型
  • Formatting context:块级上下文格式化,它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用

块格式化上下文(BFC)是Web 页面的可视化CSS渲染的一部分,是布局过程中生成块级盒子的区域,也是浮动元素与其他元素的交互限定区域。

通俗来讲:BFC是一个独立的布局环境,可以理解为一个容器,在这个容器中按照一定规则进行物品摆放,并不会影响其他环境中的物品。如果一个元素符合触发BFC的条件,则BFC中的元素受外部影响

创建BFC的条件:

  • 根元素:body;
  • 元素设置浮动: float 除none以外的值;
  • 元素设置绝对定位: position(absolute、fixed)
  • display 值为: inline-block、table-cell、table-caption、flex等
  • overflow 值为: hidden、auto、scrol

BFC 的作用:

  • 解决margin的重叠问题: 由于BFC是一个独立的区域,内部的元素和外部元素互不影响,将两个元素变成两个BFC,就解决了margin重叠的问题。
  • **解决高度塌陷的问题:**在对子元素设置浮动后,父元素会发生高度塌陷,也就是父元素的高度变成为0. 解决这个问题,只需要把父元素变成一个BFC。常用的办法是给父元素设置 overflow:hidden
  • 创建自适应两栏布局: 可以用来创建自适应两栏布局:左边的宽度固定,右边的宽度自适应
.left{
   
     width: 100px;
     height: 200px;
     background: red;
     float: left;
 }
 .right{
   
     height: 300px;
     background: blue;
     overflow: hidden;
 }
 
<div class="left"></div>
<div class="right"></div>

左侧设置float:left,右侧设置overflow: hidden。这样右边就触发了BFC,BFC的区域不会与浮动元素发生重叠,所以两侧就不会发生重叠,实现了自适应两栏布局。