Web前端高频面试题解析(javascript篇)--- 每日十题(2)

目录

1.与(&&)和或(||)操作符的返回值

1.或(||)

2.与(&&)

2.==操作符的强制类型转换规定

1.字符串和数字之间的相等比较

2.其他类型和布尔类型之间的相等比较

3.null和undefined之间的相等比较

4.对象和非对象之间的相等比较

5.如果两个操作值都是对象

3.isNaN和Number.isNaN的区别

1.isNaN

 isNaN的判断过程:

2. Number.isNaN(ES6的Number对象扩展方法)

Number.isNaN判断过程:

4.const定义的对象的属性修改

5.let,const,var的用法及区别

1.var

1.使用var声明的变量既是顶级变量(顶层对象(window对象)的属性)也是全局变量

​编辑

2.使用var声明的变量存在变量提升(提升变量声明)的情况

3.使用var可以对一个变量进行多次声明,后面的声明会覆盖前面的变量声明

4.再函数中再次使用var声明这个变量的时候,这个变量就是局部的,如果不是用var,那就是全局的

2.let

1.let所声明变量只在let命令所在的代码块中生效

2.let不存在变量提升

3.let不允许再相同的作用域下重复声明

3.const

1.const声明一个只读的常量;一旦声明,常量的值就不能改变

2.const一旦声明,就必须赋值

3.除了以上的两个,其他都和let一样

4.区别

1.变量提升:

2.块级作用域:

3.重复声明:

4.修改声明的变量:

6.如何判断一个对象是空对象

1.为什么不直接判断

2.使用JSON自带的.stringify方法来判断

3.使用Object.keys( )来判断

7.ES6中new一个箭头函数

1.new关键字的执行过程

2.箭头函数

8.ES6中扩展运算符(...)的作用

1.复制(浅拷贝)

1.数组的复制

2.对象的复制

2.合并

1.数组的合并

2.对象的合并 

3.字符串改为数组

9.ES6中的rest参数

10.ES6中对象和数组的解构

1.数组的解构

2.对象的解构

多层嵌套解构


1.与(&&)和或(||)操作符的返回值

1.或(||)

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

// 如果第一个操作数为真,返回第一个操作数的值
console.log(1 || 2)//1(真)
// 如果第一个操作数为假,返回第二个操作数的值
console.log(0 || 2)//2(真)

2.与(&&)

// 如果第一个操作数为真,返回第二个操作数的值
console.log(1 && 0)//0(假)
// 如果第一个操作数为假,返回第一个操作数的值
console.log(0 && 2)//0(假)

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

2.==操作符的强制类型转换规定

判断两者类型是否相同。如果不相同会进行类型转换;相同的话就比较大小。

转换情况:

1.字符串和数字之间的相等比较

将字符串转换为数字之后再进行比较大小。

1=='1'-->1==1-->true

2.其他类型和布尔类型之间的相等比较

先将布尔值转换为数字后,再应用其他规则进行比较。

true == '1'-- > 1 == '1'-- > 1 == 1-- > true

3.null和undefined之间的相等比较

结果为真true,其他值和它们进行比较都返回假值false

4.对象和非对象之间的相等比较

会将对象先转为基本数据类型再进行判断。

'1'=={}-->'1'=='[object object]'

5.如果两个操作值都是对象

则比较它们是不是指向同一个对象,如果两个操作数都指向同一个对象,则相等操作符返回true,否则返回false。

var a = {}
var b = a//a的引用地址赋值给b
var c = {}
console.log(a == b)//true
console.log(a == c)//false

  1.  [] 和 {} 都是属于引用类型,
  2. 引用类型是存放在堆内存中的,
  3. 而在栈内存中会有一个或者多个地址来指向这个堆内存相对应的数据。
  4. 所以在使用 == 操作符的时候,对于引用类型的数据,比较的是地址,而不是真实的值。

3.isNaN和Number.isNaN的区别

1.isNaN

isNaN:为了判断一个计算结果或者变量的值是否为NaN

isNaN(value):value表示检测的值

 isNaN的判断过程:

  1. 首先进行类型检查
  2. 如果传入的参数不是数值类型
  3. 将传入的参数转为数值类型
  4. 再进行是否为NaN的判断
    Number('')//0
    Number(null)//0
    Number(true)//1
    Number(false)//0
    Number(undefined)//NaN
    Number('aa')//NaN

    console.log(isNaN(NaN))//true
    console.log(isNaN(true))//-->1-->false
    console.log(isNaN('aaa'))//true
    console.log(isNaN(null))//-->0-->false
    console.log(isNaN(''))//0-->false
    console.log(isNaN(undefined))//true

2. Number.isNaN(ES6的Number对象扩展方法)

Number.isNaN(value):value表示检测的值

Number.isNaN判断过程:

  1. 首先进行类型检测
  2. 如果传入的参数不是数值类型,直接返回false(第一步)
  3. 如果判断出来的是数值类型,然后才会用isNaN()的方式进行判断(第二步)
    console.log(Number.isNaN(true))//第一步-->false
    console.log(Number.isNaN(''))//第一步-->false
    console.log(Number.isNaN(null))//第一步-->false
    console.log(Number.isNaN(NaN))//第二步-->true
    console.log(Number.isNaN(123))//第二步-->false
    console.log(Number.isNaN('aaaa'))//第一步-->false
    console.log(Number.isNaN(undefined))//第一步-->false

4.const定义的对象的属性修改

const定义的对象的属性可以修改吗?可以

const保证的并不是变量的值不能改动,而是变量指向的内存地址不能改动。

const obj = { name: 'zz', age: 18 }
obj.name = 'li'
console.log(obj)//age: 18,name: "li"

obj = {}//Assignment to constant variable.不能够赋值,因为不是改变的属性,是改变的对象

 

5.let,const,var的用法及区别

1.var

1.使用var声明的变量既是顶级变量(顶层对象(window对象)的属性)也是全局变量

var a = 10
console.log(window)
console.log(window.a)//10

2.使用var声明的变量存在变量提升(提升变量声明)的情况

console.log(b)//undefined
var b = 20//初始化:声明并且赋值

// 执行过程
// var b
// console.log(b)
// b = 10

3.使用var可以对一个变量进行多次声明,后面的声明会覆盖前面的变量声明

var c = 10
var c = 30
console.log(c)//30

4.再函数中再次使用var声明这个变量的时候,这个变量就是局部的,如果不是用var,那就是全局的

//局部
var d1 = 10
function fun1 () {
      var d1 = 20
}
fun1()
console.log(d1)//10

//全局
var d2 = 10
function fun1 () {
      d2 = 20
}
fun1()
console.log(d2)//10

2.let

1.let所声明变量只在let命令所在的代码块中生效

块级作用域 
//错误
{
      let num = 10
}
console.log(num)//num is not defined

//正确
{
let num = 10
console.log(num)//10
}

2.let不存在变量提升

//报错
console.log(num1)//Cannot access 'num1' before initialization
let num1 = 10

//只声明不报错
let num1
console.log(num1)//undefined

var num1
console.log(num1)//undefined

3.let不允许再相同的作用域下重复声明

//出错
let num2
console.log(num2)//Identifier 'num2' has already been declared
let num2 =10

3.const

1.const声明一个只读的常量;一旦声明,常量的值就不能改变

const a = 7
a = 77
console.log(a)//Assignment to constant variable.
赋值给常数变量-->不能再次赋值

2.const一旦声明,就必须赋值

const total
console.log(total);//Missing initializer in const declaration
缺少初始值

3.除了以上的两个,其他都和let一样

4.区别

1.变量提升:

var声明的变量存在变量提升,let和const不存在变量提升

2.块级作用域:

var不存在块级作用域,let和const存在块级作用域,只在所在代码块生效

3.重复声明:

var允许重复声明,let和const不允许在同一个作用域下重复声明

4.修改声明的变量:

var和let可以改变声明的变量;const不可以,一旦声明,必须赋值,并且常量的值不能改变

6.如何判断一个对象是空对象

在开发中,前端需要跟后端进行信息交互的,需要拿到后端返回过来的数据,再根据这个数据去渲染页面,如果网络延迟,数据在页面渲染之前没有拿到的话,在渲染这个页面的时候就会报错,报找不到这个属性。为了避免这个错误,就需要判断一下后台返回过来的数据有没有。

1.为什么不直接判断

if({}==={}){}
console.log({} === {})//false

因为对象是引用类型,因为引用地址是不一样的。 

2.使用JSON自带的.stringify方法来判断

    var obj = {}
    console.log(JSON.stringify(obj))
    if (JSON.stringify(obj) === "{}") {
      console.log("是一个空对象")
    }
    //{}
    //是一个空对象
    
    var obj = { name: 'zz' }
    console.log(JSON.stringify(obj))
    if (JSON.stringify(obj) === "{}") {
      console.log("是一个空对象")
    }
    //{"name":"zz"}

3.使用Object.keys( )来判断

key:键名;value:键值

数组 长度不等于0的话,就是有对象;等于0就是空对象。

var obj1 = {}
// 返回的是一个数组,
console.log(Object.keys(obj1))//[]
if (Object.keys(obj1).length == 0) {
      console.log('是一个空对象')
}
//[]
//是一个空对象
    
var obj2 = { name: 'zz', age: 10 }
// 返回的是一个数组
console.log(Object.keys(obj2))//(2) ['name', 'age']
if (Object.keys(obj2).length == 0) {
      console.log('是一个空对象')
}
//['name', 'age']

7.ES6中new一个箭头函数

在ES6中new一个箭头函数会怎么样?会报错

1.new关键字的执行过程

1.new 构造函数会在内存中创建一个空对象

2.this就会指向刚才创建的这个空对象(this是动态的)

3.执行构造函数中的代码,给空对象添加属性和方法

4.返回这个新的对象(所以构造函数中不需要return)

2.箭头函数

箭头函数内的this是静态的,指向定义是所在的对象,而不是调用的时侯。this指向是不可以改变的。

var d = 10
var obj = {
  d: 7,
  // 普通函数
  a: function () {
        // 谁调用这个函数,this就指向谁
        console.log(this.d)
  },
  // 箭头函数
  b: () => {
        // this是静态的,指向定义时所在的对象(window对象)
        console.log(this.d)
  }
}
obj.a()//指向obj,7
obj.b()//指向window的id,10
console.log(new obj.a())//undefined
// a作为箭头函数的存在,this就会指向刚才创建的这个空对象,这个空对象里面没有id,所以undefined
console.log(new obj.b())//a {}
// obj.b is not a constructor 不是构造函数 !!箭头函数不能当成构造函数来使用!!

8.ES6中扩展运算符(...)的作用

作用:将一个数组变为一个以空格分隔开的参数序列。

1.复制(浅拷贝)

1.数组的复制

// 如果数组里面存放的是基本数据类型-->深拷贝,引用数据类型-->浅拷贝
var arr1 = [1, 2, 3, 4, [99]]
var arr2 = [...arr1]
arr1[0] = 7
arr1[4][0] = 7
console.log(arr1)//[7, 2, 3, 4,[7]]
console.log(arr2)//[1, 2, 3, 4,[7]]

2.对象的复制

看里面的元素,如果里面保存的是引用数据类型,则是浅拷贝;如果是基本数据类型,则是深拷贝。

var obj1 = { name: 'zz', age: 12, person: { name: 'll' } }
var obj2 = { ...obj1 }
obj1.age = 7
obj1.person.name = 'nihao'
console.log(obj1)//{name: 'zz', age: 7, person: {name: 'nihao'}}
console.log(obj2)//{name: 'zz', age: 12, person: {name: 'nihao'}}

2.合并

1.数组的合并

var arr3 = [1, 2, 3]
var arr4 = [7, 7]
var arr5 = [...arr3, ...arr4]
console.log(arr5)//(5) [1, 2, 3, 7, 7]

2.对象的合并 

var obj3 = { a: 'zz' }
var obj4 = { age: 11 }
var obj5 = { ...obj3, ...obj4 }
console.log(obj5)//{a: 'zz', age: 11}

3.字符串改为数组

var myArr = [...'hello']
console.log(myArr)//(5) ['h', 'e', 'l', 'l', 'o']

9.ES6中的rest参数

用于获取函数多余的参数,形式:(...变量名),也可以把一个分离的参数序列整合为一个数组,值是一个数组。

rest参数只能放在最后一个

函数参数不确定的时候,使用rest参数

function func (...argus) {
      console.log(argus)//Array(3)[1,2,3]
      let total = 0
      for (let value of argus) {
        total += value
      }
      console.log(total) // 6
}
func(1, 2, 3)

// 当第一个传进来的参数不需要计数时,可以把第一个参数定义为形参a,接收1
function func (a, ...argus) {
      console.log(argus)//Array(2)[2,3]
      let total = 0
      for (let value of argus) {
        total += value
      }
      console.log(total) //5
}
func(1, 2, 3)

function func (a, b, ...argus, c) {// Rest parameter must be last formal parameter

10.ES6中对象和数组的解构

解构:一种提取数据的模式。

1.数组的解构

以元素的位置(下标)为匹配条件

下标
const [a, b, c] = [1, 2, 3]
//                 0  1  3
console.log(a, b, c);//1 2 3
const [a, , c] = [1, 2, 3]
console.log(a, c)//1 3

2.对象的解构

 是以属性的名称为匹配条件。

以前
const obj = { name: 'zz', age: 10 }
console.log(obj.name)//zz
console.log(obj.age)//10
现在
const obj1 = { name: 'zz', age: 10 }
const { name, age } = obj
// const { name: name, age: age } = { name: 'zz', age: 10 }
console.log(name)//zz
console.log(age)//10

多层嵌套解构

const obj2 = { a: 'zz', b: 10, children: { c: 'll', d: 7 } }
const { children: { c } } = obj2
console.log(c)//ll
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值