为了账号安全,请及时绑定邮箱和手机立即绑定
慕课专栏

目录

索引目录

高薪之路—前端面试精选集

原价 ¥ 58.00

立即订阅
07 类型与类型转换
更新时间:2020-05-04 10:27:16
完成工作的方法,是爱惜每一分钟。

——达尔文

前面提到了类型判断,JavaScript 的变量类型也是面试中经常考察的知识点。本节收集了一些类型相关的面试真题。

1. JavaScript 中有几种基本类型数据?请再列举几个引用对象。

答案:

7 种,分别为:Boolean,Null,Undefined,Number,BigInt,String,Symbol

列举几种引用对象:

普通对象 Object
数组对象 Array
正则对象 RegExp
函数 Function

解读:

这道题目是几乎每次面试必考的题目,一般作为开胃菜被面试官提出来。将它们分为三组,答案并不难记:

  1. 表示空:UndefinedNull
  2. 基础三大件:NumberStringBoolean
  3. 两个新类型:SymbolBigInt

顺便一提,BigInt 的作用是提供了一种方法来表示大于 253 - 1 的整数。

2. 请说一下JavaScript中的typeof操作符的用法?

答案:

typeof用来返回一个值的变量类型,对于不同类型的变量其返回值如下:

typeof undefined === 'undefined'
typeof true === 'boolean'
typeof 78 === 'number'
typeof 'hey' === 'string'
typeof Symbol() === 'symbol'
typeof BigInt(1) === 'bigint'
typeof new String('abc') === 'object'
typeof null === 'object'
typeof function(){} === 'function'
typeof {name: 'Jack'} === 'object'

解读:

注意typeof是用来返回的类型,而不是返回**变量的类型,**因为 JavaScript 中的变量是没有类型的,比如:

let a = 1;
console.log(typeof a) // 'number'
a = '1'
console.log(typeof a) // 'string'

a变量是没有类型的,但是赋给a变量的值确是有类型的。

typeof对于大多数对象都会返回object,一个例外是函数,对于函数会返回function。另一个要注意的是typeof对于null会返回object,这是一个历史悠久的 bug,但是由于无数的网站已经默认了这个 bug,所以现在也无法对其进行修正了。所以使用typeof判断null的方法是:

var a = null;

(!a && typeof a === "object"); // true

3. 什么是 JavaScript 中的包装类型?

答案:

在 JavaScript 中,基本类型是没有属性和方法的,但是为了便于操作基本类型的值,在调用基本类型的属性或方法时 JavaScript 会在后台隐式地将基本类型的值转换为对象,如:

const a = "abc";
a.length; // 3
a.toUpperCase(); // "ABC"

在访问'abc'.length时,JavaScript 将'abc'在后台转换成String('abc'),然后再访问其length属性。

解读:

JavaScript也可以使用Object函数显式地将基本类型转换为包装类型:

var a = 'abc'
Object(a) // String {"abc"}

也可以使用valueOf方法将包装类型倒转成基本类型:

var a = 'abc'
var b = Object(a)
var c = b.valueOf() // 'abc'

请猜测如下代码会打印出什么:

var a = new Boolean( false );

if (!a) {
	console.log( "Oops" ); // never runs
}

答案是什么都不会打印,因为虽然包裹的基本类型是false,但是false被包裹成包装类型后就成了对象,所以其非值为false,所以循环体中的内容不会运行。

4. 如何使用Object.prototype.toString来判断值的类型,为什么使用它可以判断值的类型?

答案:

在任何值上调用Object.prototype.toString方法,都会返回一个 [object NativeConstructorName]格式的字符串。每个类在内部都有一个 [[Class]] 属性,这个属性中就指定了上述字符串中的构造函数名。

Object.prototype.toString.call({name:'Jack'}) // [object Object]
Object.prototype.toString.call(function(){}) // [object Function]
Object.prototype.toString.call(/name/) // [object RegExp]

而对于基本类型:

Object.prototype.toString.call('abc') // [object String]
Object.prototype.toString.call(12) // [object Number]
Object.prototype.toString.call(true) // [object Boolean]

基本类型值是没有构造函数的,为什么也能返回构造函数名呢?这是因为在toString被调用时 JavaScript 将基本类型值转换成了包装类型。

而对于nullundefined

Object.prototype.toString.call( null );			// "[object Null]"
Object.prototype.toString.call( undefined );	// "[object Undefined]"

虽然 JavaScript 中没有Null()Undefined构造器,但是 JavaScript 也为我们处理这这两种情况。

5. JavaScript 中如何进行显式类型转换?

JavaScript 的类型转换的结果总是得到stringnumberboolean类型的一种。

  1. stringnumber

stringnumber 类型的值进行互相转换,分别使用StringNumber函数:

const a = 18
const b = String(18) // '18'
const c = Number(b) // 18

numberstring 类型转换还可以使用toString方法:

const a = 18
const b = a.toString() // '18'

stringnumber类型转换还可以使用一元操作符+

const a = '18'
const b = +a //18

stringnumber类型转换还可以使用parseInt

const a = '18px'
const b = parseInt(a) // 18
const c = Number(a) // NaN

可以看出,parseIntNumber不同的地方在于,parseInt允许传入非数字字符 (例如px),其从左往右解析,遇到非数字字符就会停下。而Number不允许传入非数字字符。

  1. 任意值转换成boolean

使用Boolean函数来显式地将任意值转成boolean,如:

const a = '123'
const b = undefined
const c = 0
Boolean(a) // true
Boolean(b) // false
Boolean(c) // false

实践中最常用的方法是使用!!符号:

const a = '123'
const b = undefined
const c = 0
!!a // true
!!b // false
!!c // false

解读:

注意题目中的类型转换是这种形式:String(123),而不是这样:new String(123),因为第一个才是进行包装类型转换,而第二个是生成实例。

关于一元操作符+还有一个用法,那就是将日期对象转换成number

var date = new Date( "Mon, 1 Mar 2020 08:53:06" )
+date // 1583013186000

6. JavaScript 中如何进行隐式类型转换?

解答:

首先要介绍ToPrimitive方法,这是 JavaScript 中每个值隐含的自带的方法,用来将值 (无论是基本类型值还是对象)转换为基本类型值。如果值为基本类型,则直接返回值本身;如果值为对象,其看起来大概是这样:

/**
* @obj 需要转换的对象
* @type 期望的结果类型
*/
ToPrimitive(obj,type)

type的值为number或者string

typenumber时规则如下:

  1. 调用objvalueOf方法,如果为原始值,则返回,否则下一步;
  2. 调用objtoString方法,后续同上;
  3. 抛出TypeError 异常。

typestring时规则如下:

  1. 调用objtoString方法,如果为原始值,则返回,否则下一步;
  2. 调用objvalueOf方法,后续同上;
  3. 抛出TypeError 异常。

可以看出两者的主要区别在于调用toStringvalueOf的先后顺序。默认情况下:

  1. 如果对象为 Date 对象,则type默认为string
  2. 其他情况下,type默认为number

而 JavaScript 中的隐式类型转换主要发生在+、-、*、/以及==、>、<这些运算符之间。而这些运算符只能操作基本类型值,所以在进行这些运算前的第一步就是将两边的值用ToPrimitive转换成基本类型,再进行操作。

以下是基本类型的值在不同操作符的情况下隐式转换的规则 (对于对象,其会被ToPrimitive转换成基本类型,所以最终还是要应用基本类型转换规则):

  1. +操作符
    +操作符的两边有至少一个string类型变量时,两边的变量都会被隐式转换为字符串;其他情况下两边的变量都会被转换为数字。
 1 + '23' // '123'
 1 + false // 1 
 1 + Symbol() // Uncaught TypeError: Cannot convert a Symbol value to a number
 '1' + false // '1false'
 false + true // 1
  1. -*\操作符
    这三个操作符是为数字操作而设计的,所以操作符两边的变量都会被转换成数字,注意NaN也是一个数字
 1 * '23' // 23
 1 * false // 0
 1 / 'aa' // NaN
  1. 对于==操作符

操作符两边的值都尽量转成number

3 == true // false, 3 转为number为3,true转为number为1
'0' == false //true, '0'转为number为0,false转为number为0
'0' == 0 // '0'转为number为0
  1. 对于<>比较符

如果两边都是字符串,则比较字母表顺序:

'ca' < 'bd' // false
'a' < 'b' // true

其他情况下,转换为数字再比较:

'12' < 13 // true
false > -1 // true

以上说的是基本类型的隐式转换,而对象会被ToPrimitive转换为基本类型再进行转换:

var a = {}
a > 2 // false

其对比过程如下:

a.valueOf() // {}, 上面提到过,ToPrimitive默认type为number,所以先valueOf,结果还是个对象,下一步
a.toString() // "[object Object]",现在是一个字符串了
Number(a.toString()) // NaN,根据上面 < 和 > 操作符的规则,要转换成数字
NaN > 2 //false,得出比较结果

又比如:

var a = {name:'Jack'}
var b = {age: 18}
a + b // "[object Object][object Object]"

运算过程如下:

a.valueOf() // {},上面提到过,ToPrimitive默认type为number,所以先valueOf,结果还是个对象,下一步
a.toString() // "[object Object]"

b.valueOf() // 同理
b.toString() // "[object Object]"

a + b // "[object Object][object Object]"

总结:

由于 JavaScript 的弱类型语言特性,它过于灵活的类型转换规则确实给开发者带来不少烦恼。特别是隐式转换,其实在实际开发中并不会遇到这么多题目中的情况,但是类似题目确实是面试中的常考题,建议大家多看多记。

}
立即订阅 ¥ 58.00

你正在阅读课程试读内容,订阅后解锁课程全部内容

千学不如一看,千看不如一练

手机
阅读

扫一扫 手机阅读

高薪之路—前端面试精选集
立即订阅 ¥ 58.00

举报

0/150
提交
取消