JavaScript数据类型相关面试知识点总结

匿名网友 匿名网友 发布于: 2015-10-29 00:00:00
阅读 170 收藏 0 点赞 0 评论 0

运算符

h1.section { background: lightblue; color: white; padding: 10px; }

一个概念问题:基本数据类型,简单数据类型,原始数据类型 —— 简单 = 原始 < 基本

分类:

原始类型(简单类型):

  • 数字(the number type)
  • 字符串(the string type)
  • 布尔值(the boolean type)
  • null (the null type)
  • undefined (the undefined type)

对象类型(复杂类型):Object

  • 内置对象类型:Funciton, Date, Error, JSON, Promise等 (more)
  • 原始类型的包装对象(wrapper object):Number, String, Boolean
  • 可用直接量表示的:Object, Array, Function, RegExp, 以及wrapper object

原始类型与对象类型的区别与联系:

区别:

  1. 原始类型的值保存在栈中,对象类型的值保存着堆中
  2. 原始类型是不可变的(immutable), 对象类型是可变的(mutable)
  3. 给变量赋值的时候,原始类型赋的是值,对象类型赋的是引用
  4. 原始类型没有属性,对象类型有
    > var str = "text"  //str为原始类型
    undefined
    > var strObj = new String("text") //strObj为对象类型
    undefined
    > str.newProperty = 1 //给str创建一个属性并赋值
    1
    > strObj.newProperty = 1 //给strObj创建一个属性并赋值
    1
    > str.newProperty
    undefined
    > strObj.newProperty
    1

    为什么给str创建属性不会报错呢?这涉及到自动包装,请看“联系”部分。

  5. 对象类型可以用new操作符创建,原始类型不能,原始类型可以通过直接量创建或者由对象的某些方法返回得到(toString(), valueOf()

联系:auto-boxing

  • 当在原始类型值上进行添加属性、调用方法等只能在对象上进行的操作时,JS会自动创建该原始类型相应的包装对象,并在该包装对象上进行操作,所以不会报错,但操作结束后这个对象就立即被销毁了。所以
    > var str = "text"  //str为原始类型
    undefined
    > str.newProperty = 1 //给str创建一个属性并赋值
    1
    > str.newProperty
    undefined

    这里的第二条语句在执行时实际上创建了一个new String(str),但在第三条语句执行的时候,刚刚创建的那个对象已经不在了。

  • 当用callapply方法传入的第一个参数(this指向的那个)是原始类型时,在非strict模式下,除了nullundefined会被全局对象取代,其他原始类型会转换为相应于的包装对象。

各类型要点:

数字类型 (The Number Type)

  • 值:-Infinity, 负数, -0, 0, +0, 正数, (+)Infinity, NaN
  • 进制:默认十进制,0X或者0x开头为十六进制
    • 进制转换可用parseInt(value, digit)方法
  • NaN
    • NaN与任何值都不相等,包括它自己
    • 判断变量x是否是NaN的方法:
    1. 判断x!=x, 如果结果为true, 表示x的值为NaN, 因为只有NaN不与自己相等
    2. isNaN(x)检测NaN

      isFinite(x)排除NaN, Infinity, -Infinity

字符串 (The String Type)

本节讨论的是字符串直接量,而非String包装对象(new String())

  • length属性计算的是字符串包含的16位值得个数,有些字符不能表示为16位的字符将采用utf-16编码规则——用两个16位值组成。所以,有些字符的长度可能为2。
    > "e".length
    1
    > '?'.length
    2

    然而这种情况比较少见

  • Using JavaScript’s Array Methods on Strings

布尔值 (The Boolean Type)

暂时没什么好说的

null

  • 注意typeof javascript var car = null; alert(typeof car); //"object"

undefined

  • 注意typeof:不仅未赋值的变量是”undefined”, 就连本身会报错的未声明变量 javascript > var ab; // 声明了ab,但没赋值 > typeof ab 'undefined' // 这个结果是理所应当的 > typeof adfasdf //adfasdf是什么鬼,根本没声明过的东西 'undefined' // 然而。。却得到和声明过的变量一样的待遇,confusing huh? 记住就好!

对象 (Object)

暂时没甚好说的

类型检测:

  • typeof只有七个可能的值:"number","string","boolean","undefined","object","function","symbole"(ECMAscript 2015)
  • instanceof检查的是实例的[[Prototpye]](或者__proto__)与构造函数的prototype属性是否相等:
> var arr = [];
undefined
> arr instanceof Array //事实上检查的是 arr.__proto__ === Array.prototype (true)
true
  • constructor可以通过prototype进行修改

Object.prototype.toString.call无法区分自定义的类型

检测null, undefined:

分别直接检查值是否 === null=== undefined, 不能用==,因为会进行类型转换

> var i = null;
undefined
> var j = {};
undefined
> j === null
false
> i === null
true
> var hahah;
undefined
> hahah === undefined
true
> safasdf === undefined  //为声明变量正常报错~ typeof can never!
ReferenceError: safasdf is not defined
    at repl:1:1
    at REPLServer.defaultEval (repl.js:132:27)
    at bound (domain.js:254:14)
    at REPLServer.runBound [as eval] (domain.js:267:12)
    at REPLServer.<anonymous> (repl.js:279:12)
    at REPLServer.emit (events.js:107:17)
    at REPLServer.Interface._onLine (readline.js:214:10)
    at REPLServer.Interface._line (readline.js:553:8)
    at REPLServer.Interface._ttyWrite (readline.js:830:14)
    at ReadStream.onkeypress (readline.js:109:10)

检测原始类型的number, boolean, string: typeof

> typeof 1
'number'
> typeof 1.2
'number'
> typeof 1.200
'number'
> typeof 0x1233
'number'
> typeof 0123
'number'
> typeof Infinity
'number'
> typeof -0
'number'
> typeof NaN
'number'
> typeof new Number(3)
'object'
> typeof "2"
'string'
> typeof "\n"
'string'
> typeof 'c'
'string'
> typeof new String("test")
'object'
> typeof "true"
'string'
> typeof true
'boolean'
> typeof false
'boolean'
> typeof new Boolean(false)
'object'

检测对象类型:typeof

  • 注意:除了Function和Symbol,所有类型的对象,typeof都是object
> typeof new Function()
'function'
> typeof new String()
'object'
> typeof new Date()
'object'
> typeof new RegExp()
'object'
> typeof new Number()
'object'
> typeof new Object()
'object'
> function MyObject() {}
undefined
> typeof new MyObject()
'object'
> typeof MyObject
'function'
  • 检测各种不同的Object类型
    • 内置对象:Object.prototype.toString.call(obj)
> Object.prototype.toString.call(new String())
'[object String]'
> Object.prototype.toString.call(new Date())
'[object Date]'
> Object.prototype.toString.call(new Boolean())
'[object Boolean]'
> Object.prototype.toString.call(new Error())
'[object Error]'
> Object.prototype.toString.call(new URIError())
'[object Error]'
> Object.prototype.toString.call(new RegExp())
'[object RegExp]'
> Object.prototype.toString.call(new Array())
'[object Array]'
> Object.prototype.toString.call(new Map())
'[object Map]'
> function Haha() {}
undefined
> Object.prototype.toString.call(new Haha())  //非内置的自定义对象无法得到准确的类型名
'[object Object]'
  • 自定义对象:
    • 区别非同一原型链上的对象:instanceof
> var myObject = new MyObject()
undefined
> myObject instanceof MyObject
true
> myObject instanceof Object  //也是“父类”的instance
true
  • 区分同一原型链上的对象:constructor(缺点是,可以被修改)
> myObject.constructor === Object
false
> myObject.constructor === MyObject
true
> MyObject.prototype.constructor = String  //把constructor改掉
[Function: String]
> myObject.constructor === MyObject //就检测不到了
false

类型转换:

途径:

  1. 调用String(), Number(), Boolean(), Object()(隐式转换的效果与此相同)
    • 对数字、字符串、布尔值调用Object()其实就是自动包装对象auto-boxing, 如2变成new Number(2)
    • Object()undefinednull转成{}, 这只能通过显示转换实现
    • 需要注意的Number()转换: javascript > Number(undefined) NaN > Number(null) 0 > Number([9]) 9 > Number(['9']) 9 > Number(['9',3]) NaN > Number(['A']) NaN > Number("Infinity") Infinity > +"Infinity" Infinity > Number("-Infinity") -Infinity > Number("-0") -0 > Number("0") 0 > Number("NaN") NaN
  2. toString():与String()效果相同,但不同的是,此方法对null,undefined无效
  3. 对象到布尔值:所有对象都会转为true, 包括new Boolean(false) javascript > !!new Boolean(false) true
  4. JS试图将内置对象转为字符串的过程:先尝试toString(),如果失败(没得到原始值),再尝试valueOf(), 若最终得到原始值,将原始值转为字符串,否则报错。
  5. JS试图将内置对象转为数字的过程:先尝试valueOf(),如果失败(没得到原始值),再尝试toString(), 若最终得到原始值,将原始值转为数字,否则报错。
  6. 宿主对象有各自的算法转换为数字或字符串。
  7. 更多字符串-数字相互转换方法:
    • 数字转为字符串:
      • toFixed(n): 四舍五入保留n位小数
      • toExponential(n): 用科学计数法表示的字符串,小数点后保留n位
      • toPrecision(n): 保留n位有效数字
    • 字符串转为数字:
      • parseInt(string, [声明第一个参数的进制]) 返回十进制整数或NaN
      • parseFloat(string) 返回小数或NaN
  8. 特殊内置对象的toString()方法:
    • 数组:各元素用逗号相连的字符串 (注意与JAVA区分,JS中打印数组没有”[]”)
    • 函数:函数定义的代码
    • 正则:直接量的字符串
    • 日期:一个表示详细日期时间信息的字符串,如'Thu Oct 15 2015 23:37:56 GMT+0800 (中国标准时间)'
  9. valueOf()方法:
    • 如果存在任意原始值,就返回原始值
    • 默认返回对象本身(数组、函数、正则——返回对象本身)
    • 日期:返回毫秒数

运算符与类型转换

  1. 算术运算符一元+, 一元-, ++, --, +, -, *, /, %:
    • 二元+:
      • 如果有一个操作数是字符串,就会把另一个转为字符串
      • 如果有操作数是对象,会先尝试把对象转为原始值,如果转换后有字符串,就进行上一步的操作,否则,将两个原始值转为数字
      • 如果两个都是数字,直接相加;如果两个都是字符串,直接连接。
    • 除了二元+, 其余都将操作数转为数字类型
    • /运算符的结果为浮点型(与JAVA不同)
    • %运算符的结果为浮点型,甚至操作数都可以是浮点型 6.5%2.1的结果为0.2
  2. 比较运算符==, !=, ===, !==, <, >, <=, >=
    • ===!==不进行类型转换,直接比值
    • ==!=会对类型不同的两个数进行类型转换,转换成相同的类型后,按照严格相等===的规则来比较,类型转换的规则如下:
      • 如果是null和undefined,它们相等
      • 如果是数组和字符串,字符串转为数字(数字比字符串更容易比较)
      • 布尔值转为数字
      • 如果是对象和原始值,对象转为原始值(对内置对象而言,除了日期对象,其他的先尝试valueOf(), 再尝试toString()
    • <, >, <=, >=的转换规则:
      • 有对象,先转为原始值
      • 两个原始值:如果两个都是字符串,参照String.localeCompare()比较;如果至少有一个不是字符串,都转为数字
      • NaN和任何数比较,结果都是false
  3. +更偏爱字符串,比较运算符更偏爱数字
  4. in运算符:把左操作数转为字符串,右操作数转为对象
  5. instanceof运算符期待左操作符是一个对象,如果不是的话,不会进行自动转换!!!,而是返回false
  6. 一元!将其操作数转为布尔值并取反

评论列表
文章目录