You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
//ES5 Version
function add(a,b){
a = a || 0;
b = b || 0;
return a + b;
}
//ES6 Version
function add(a = 0, b = 0){
return a + b;
}
add(1); // returns 1
let a;
console.log(parseInt('abc')); // NaN
console.log(parseInt(null)); // NaN
console.log(parseInt(undefined)); // NaN
console.log(parseInt(++a)); // NaN
console.log(parseInt({} * 10)); // NaN
console.log(parseInt('abc' - 2)); // NaN
console.log(parseInt(0 / 0)); // NaN
console.log(parseInt('10a' * 10)); // NaN
const person = {
name: "Leonardo"
};
let animal = {
species: "snake"
};
person = animal; // ERROR "person" is read-only
Object.freeze适用于值,更具体地说,适用于对象值,它使对象不可变,即不能更改其属性。
let person = {
name: "Leonardo"
};
let animal = {
species: "snake"
};
Object.freeze(person);
person.name = "Lima"; //TypeError: Cannot assign to read only property 'name' of object
console.log(person);
function deepFreeze(object) {
let propNames = Object.getOwnPropertyNames(object);
for (let name of propNames) {
let value = object[name];
object[name] = value && typeof value === "object" ?
deepFreeze(value) : value;
}
return Object.freeze(object);
}
let person = {
name: "Leonardo",
profession: {
name: "developer"
}
};
deepFreeze(person);
person.profession.name = "doctor"; // TypeError: Cannot assign to read only property 'name' of object
由于篇幅过长,我将此系列分成上中下三篇,上、中篇:
看完这几道 JavaScript 面试题,让你与考官对答如流(中)
看完这几道 JavaScript 面试题,让你与考官对答如流(上)
async/await
及其如何工作?%
模运算符的情况下检查一个数字是否是偶数?Iterator
是什么,有什么作用?Generator
函数是什么,有什么作用?51. 什么是
async/await
及其如何工作?async/await
是 JS 中编写异步或非阻塞代码的新方法。它建立在Promises之上,让异步代码的可读性和简洁度都更高。async/await
是 JS 中编写异步或非阻塞代码的新方法。 它建立在Promises
之上,相对于 Promise 和回调,它的可读性和简洁度都更高。 但是,在使用此功能之前,我们必须先学习Promises
的基础知识,因为正如我之前所说,它是基于Promise
构建的,这意味着幕后使用仍然是Promise。使用 Promise
使用async/await
在
async/await
,我们使用 tru/catch 语法来捕获异常。注意:使用
async
关键声明函数会隐式返回一个Promise。注意:
await
关键字只能在async function
中使用。在任何非async function的函数中使用await
关键字都会抛出错误。await
关键字在执行下一行代码之前等待右侧表达式(可能是一个Promise)返回。52. 展开(spread )运算符和 剩余(Rest) 运算符有什么区别?
展开运算符(spread)是三个点(
...
),可以将一个数组转为用逗号分隔的参数序列。说的通俗易懂点,有点像化骨绵掌,把一个大元素给打散成一个个单独的小元素。剩余运算符也是用三个点(
...
)表示,它的样子看起来和展开操作符一样,但是它是用于解构数组和对象。在某种程度上,剩余元素和展开元素相反,展开元素会“展开”数组变成多个元素,剩余元素会收集多个元素和“压缩”成一个单一的元素。在本例中,我们在调用
add
函数时使用了展开操作符,对nums
数组进行展开。所以参数a
的值是5
,b
的值是6
,所以sum
是11
。在本例中,我们有一个
add
函数,它接受任意数量的参数,并将它们全部相加,然后返回总数。这里,我们使用剩余操作符提取所有剩余的数组值,并将它们放入除第一项之外的其他数组中。
53. 什么是默认参数?
默认参数是在 JS 中定义默认变量的一种新方法,它在ES6或ECMAScript 2015版本中可用。
我们还可以在默认参数中使用解构。
我们还可以使用先定义的参数再定义它们之后的参数。
54. 什么是包装对象(wrapper object)?
我们现在复习一下JS的数据类型,JS数据类型被分为两大类,基本类型和引用类型。
基本类型:
Undefined
,Null
,Boolean
,Number
,String
,Symbol
,BigInt
引用类型:
Object
,Array
,Date
,RegExp
等,说白了就是对象。其中引用类型有方法和属性,但是基本类型是没有的,但我们经常会看到下面的代码:
name
类型是string
,属于基本类型,所以它没有属性和方法,但是在这个例子中,我们调用了一个toUpperCase()
方法,它不会抛出错误,还返回了对象的变量值。原因是基本类型的值被临时转换或强制转换为对象,因此
name
变量的行为类似于对象。 除null
和undefined
之外的每个基本类型都有自己包装对象。也就是:String
,Number
,Boolean
,Symbol
和BigInt
。 在这种情况下,name.toUpperCase()
在幕后看起来如下:在完成访问属性或调用方法之后,新创建的对象将立即被丢弃。
55. 隐式和显式转换有什么区别)?
隐式强制转换是一种将值转换为另一种类型的方法,这个过程是自动完成的,无需我们手动操作。
假设我们下面有一个例子。
第一个
console.log
语句结果为16
。在其他语言中,这会抛出编译时错误,但在 JS 中,1
被转换成字符串,然后与+运
算符连接。我们没有做任何事情,它是由 JS 自动完成。第二个
console.log
语句结果为1
,JS 将false
转换为boolean
值为0
,,true
为1
,因此结果为1
。第三个
console.log
语句结果12
,它将'2'
转换为一个数字,然后乘以6 * 2
,结果是12。而显式强制是将值转换为另一种类型的方法,我们需要手动转换。
在本例中,我们使用
parseInt
函数将'6'
转换为number
,然后使用+
运算符将1
和6
相加。56. 什么是NaN? 以及如何检查值是否为NaN?
NaN
表示**“非数字”**是 JS 中的一个值,该值是将数字转换或执行为非数字值的运算结果,因此结果为NaN
。JS 有一个内置的
isNaN
方法,用于测试值是否为isNaN值,但是这个函数有一个奇怪的行为。所有这些
console.log
语句都返回true
,即使我们传递的值不是NaN
。在
ES6
中,建议使用Number.isNaN
方法,因为它确实会检查该值(如果确实是NaN
),或者我们可以使自己的辅助函数检查此问题,因为在 JS 中,NaN是唯一的值,它不等于自己。57. 如何判断值是否为数组?
我们可以使用
Array.isArray
方法来检查值是否为数组。 当传递给它的参数是数组时,它返回true
,否则返回false
。如果环境不支持此方法,则可以使用
polyfill
实现。当然还可以使用传统的方法:
58. 如何在不使用
%
模运算符的情况下检查一个数字是否是偶数?我们可以对这个问题使用按位
&
运算符,&
对其操作数进行运算,并将其视为二进制值,然后执行与运算。0
二进制数是000
1
二进制数是001
2
二进制数是010
3
二进制数是011
4
二进制数是100
5
二进制数是101
6
二进制数是110
7
二进制数是111
以此类推...
与运算的规则如下:
因此,当我们执行
console.log(5&1)
这个表达式时,结果为1
。首先,&
运算符将两个数字都转换为二进制,因此5
变为101
,1
变为001
。然后,它使用按位怀运算符比较每个位(
0
和1
)。101&001
,从表中可以看出,如果a & b
为1
,所以5&1
结果为1
。1&0
,结果是0
。0&0
,结果是0
。1&1
,结果是1
。001
,对应的十进制数,即1
。由此我们也可以算出
console.log(4 & 1)
结果为0
。知道4
的最后一位是0
,而0 & 1
将是0
。如果你很难理解这一点,我们可以使用递归函数来解决此问题。59. 如何检查对象中是否存在某个属性?
检查对象中是否存在属性有三种方法。
第一种使用
in
操作符号:第二种使用
hasOwnProperty
方法,hasOwnProperty()
方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。第三种使用括号符号
obj["prop"]
。如果属性存在,它将返回该属性的值,否则将返回undefined
。60. AJAX 是什么?
即异步的 JavaScript 和 XML,是一种用于创建快速动态网页的技术,传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。使用AJAX则不需要加载更新整个网页,实现部分内容更新
用到AJAX的技术:
61. 如何在 JS 中创建对象?
使用对象字面量:
使用构造函数:
使用 Object.create 方法:
62. Object.seal 和 Object.freeze 方法之间有什么区别?
Object.freeze()
Object.freeze()
方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze()
返回和传入的参数相同的对象。Object.seal()
方法的相同点:
方法不同点:
Object.seal
方法生成的密封对象,如果属性是可写的,那么可以修改属性值。* Object.freeze
方法生成的冻结对象,属性都是不可写的,也就是属性值无法更改。63.
in
运算符和Object.hasOwnProperty
方法有什么区别?hasOwnPropert方法
hasOwnPropert()
方法返回值是一个布尔值,指示对象自身属性中是否具有指定的属性,因此这个方法会忽略掉那些从原型链上继承到的属性。看下面的例子:
可以看到,如果在函数原型上定义一个变量
phone
,hasOwnProperty
方法会直接忽略掉。in 运算符
如果指定的属性在指定的对象或其原型链中,则
in
运算符返回true
。还是用上面的例子来演示:
可以看到
in
运算符会检查它或者其原型链是否包含具有指定名称的属性。64. 有哪些方法可以处理 JS 中的异步代码?
65. 函数表达式和函数声明之间有什么区别?
看下面的例子:
notHoistedFunc
调用抛出异常:Uncaught TypeError: notHoistedFunc is not a function
,而hoistedFunc
调用不会,因为hoistedFunc
会被提升到作用域的顶部,而notHoistedFunc
不会。66. 调用函数,可以使用哪些方法?
在 JS 中有4种方法可以调用函数。
作为函数调用——如果一个函数没有作为方法、构造函数、
apply
、call
调用时,此时this
指向的是window
对象(非严格模式)作为方法调用——如果一个对象的属性有一个函数的值,我们就称它为方法。调用该方法时,该方法的
this
值指向该对象。作为构造函数的调用-如果在函数之前使用
new
关键字调用了函数,则该函数称为构造函数
。构造函数里面会默认创建一个空对象,并将this
指向该对象。使用
apply
和call
方法调用——如果我们想显式地指定一个函数的this
值,我们可以使用这些方法,这些方法对所有函数都可用。67. 什么是缓存及它有什么作用?
缓存是建立一个函数的过程,这个函数能够记住之前计算的结果或值。使用缓存函数是为了避免在最后一次使用相同参数的计算中已经执行的函数的计算。这节省了时间,但也有不利的一面,即我们将消耗更多的内存来保存以前的结果。
68. 手动实现缓存方法]
这个缓存函数适用于接受一个参数。 我们需要改变下,让它接受多个参数。
69. 为什么typeof null 返回 object? 如何检查一个值是否为 null?
typeof null == 'object'
总是返回true
,因为这是自 JS 诞生以来null
的实现。曾经有人提出将typeof null == 'object'
修改为typeof null == 'null'
,但是被拒绝了,因为这将导致更多的bug。我们可以使用严格相等运算符
===
来检查值是否为null
。70. new 关键字有什么作用?
new
关键字与构造函数一起使用以创建对象:new
关键字做了4
件事:{}
this
值__proto__
指向构造函数的prototype
return
语句,则返回this
看下面事例:
function Person() {
this.name = '前端小智'
}
根据上面描述的,
new Person()
做了:var obj = {}
this
值:this = obj__proto__
指向构造函数的prototype
:this.__proto__ = Person().prototype
this
:return this
71. 什么时候不使用箭头函数? 说出三个或更多的例子?
不应该使用箭头函数一些情况:
this/arguments
时,由于箭头函数本身不具有this/arguments
,因此它们取决于外部上下文this
即对象本身。72. Object.freeze() 和 const 的区别是什么?]
const
和Object.freeze
是两个完全不同的概念。const
声明一个只读的变量,一旦声明,常量的值就不可改变:Object.freeze
适用于值,更具体地说,适用于对象值,它使对象不可变,即不能更改其属性。73. 如何在 JS 中“深冻结”对象?
如果咱们想要确保对象被深冻结,就必须创建一个递归函数来冻结对象类型的每个属性:
没有深冻结
深冻结
74.
Iterator
是什么,有什么作用?遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
Iterator
的作用有三个:for...of
循环,Iterator 接口主要供for...of
消费。遍历过程:
每一次调用
next
方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含value
和done
两个属性的对象。其中,value
属性是当前成员的值,done
属性是一个布尔值,表示遍历是否结束。75.
Generator
函数是什么,有什么作用?如果说 JavaScrip 是 ECMAScript 标准的一种具体实现、
Iterator
遍历器是Iterator
的具体实现,那么Generator
函数可以说是Iterator
接口的具体实现方式。执行
Generator
函数会返回一个遍历器对象,每一次Generator
函数里面的yield都相当一次遍历器对象的next()
方法,并且可以通过next(value)
方法传入自定义的value
,来改变Generator
函数的行为。Generator
函数可以通过配合Thunk 函数更轻松更优雅的实现异步编程和控制流管理。代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。
原文:
https://dev.to/macmacky/70-javascript-interview-questions-5gfi#1-whats-the-difference-between-undefined-and-null
交流
干货系列文章汇总如下,觉得不错点个Star,欢迎 加群 互相学习。
我是小智,公众号「大迁世界」作者,对前端技术保持学习爱好者。我会经常分享自己所学所看的干货,在进阶的路上,共勉!
关注公众号,后台回复福利,即可看到福利,你懂的。
The text was updated successfully, but these errors were encountered: