类型和语法

函数不仅是对象,还可以拥有属性。函数对象的length属性是其声明的参数的个数(希望接收参数的个数)。

JavaScript中的变量是没有类型的,只有值才有。变量可以随时持有任何类型的值。

在对变量执行typeof操作时,得到的结果并不是该变量的类型,而是该变量持有的值的类型,因为JavaScript中的变量没有类型。

变量在未持有值的时候为undefined,还没有在作用域中声明过的变量是undeclared。(is undefined 和 is not defined是两码事)

使用delete运算符可以将单元从数组中删除。单元删除后数组的length属性并不会发生变化。

数组通过数字进行索引,但也可以包含字符串键值和属性(这些并不计算在数组长度内)。

如果字符串键值能够被强制类型转换为十进制数字的话,它就会被当做数字索引来处理。

字符串不可变是指字符串的成员函数不会改变其原始值,而是创建并返回一个新的字符串。而数组的成员函数都是在其原始值上进行操作。(这也并不意味着所有的数组api都会改变原数组,不要误解。)

toFixed方法不仅适用于数字变量,也适用于数字字面量。不过对于.运算符需要给予特别注意,因为它是一个有效的数字字符,会被优先识别为数字字面量的一部分,然后才是对象属性访问运算符。

整数检测&安全的整数

if(Number.isInteger){
    Number.isInteger = function(num){
        return typeof num === 'number' && num % 1 == 0
    }
}

if(Number.isSafeInteger){
    Number.isSafeInteger = function(num){
        return Number.isInteger(num) && Math.abs(num) <= Number.MAX_SAFE_INTEGER
    }
}

isNaN(...)有一个严重的缺陷,它的检查方式过于死板,就是“检查参数是否不是NaN,也不是数字”。

NaN是JavaScript中唯一一个不等于自身的值。

if(!Number.isNaN){
    Number.isNaN = function(n){
        return n !== n
    }
}

计算结果一旦溢出为无穷数(infinity)就无法再得到有穷数。换句话说,就是你可以从有穷数走向无穷,但无法从无穷回到有穷。

验证-0(区分0与-0)

function isNegZero(n){
    n = Number(n)
    return n === 0 && 1 / n === -Infinity
}

Object.is(...)来判断两个值是否绝对相等  

if(!Object.is){
    Object.is = function(v1,v2){
        if(v1 === 0 && v2 === 0){
            return 1 / v1 === 1 / v2
        }
        if(v1 !== v1){
            return v2 !== v2
        }
        return v1 === v2
    }
}

参数值总是通过值复制的方式传递,即便对复杂的对象值也是如此。

简单值总是通过值复制的方式来赋值或传递;复合值总是通过引用复制的方法来赋值或传递。

典型面试题

let array = [1,2,3]
function foo(arr){
    arr.push(4)
    arr = [5,6,7]
    console.log(arr)//[5,6,7]
}
foo(array)
console.log(array)//[1,2,3,4]

我们无法自行决定使用值复制还是引用复制,一切由值的类型来决定。

一般情况下,我们不需要直接使用封装对象,最好是让JavaScript引擎自己决定什么时候应该使用封装对象。因为浏览器已经为这样的常见情况作了性能优化,直接使用封装对象来“提前优化”代码反而会降低执行效率。

如果想要自行封装基本类型值,可以使用Object(...)函数(不带new关键字)。

我们将包含至少一个“空单元”的数组称为“稀疏数组”。

Function.prototype是一个函数;RegExp.prototype是一个正则表达式;Array.prototype是一个数组。

将值从一种类型转换为另一种类型通常称为类型转换。

JavaScript中的强制类型转换总是返回标量基本类型值。

类型转换发生在静态类型语言的编译阶段,而强制类型转换则发生在动态类型语言的运行时(runtime)。

var a = 1;
var b = a + '';//隐式强制类型转换
var c = String(a);//显式强制类型转换

抽象操作ToString,负责处理非字符串到字符串的强制类型转换。

对普通对象来说,除非自定义,否则toString()(Object.prototype.toString())返回内部属性[[class]]的值。

如果对象有自己的toString()方法,字符串化时就会调用该方法并使用其返回值。

数组的默认toString()方法经过了重新定义,将所有单元字符串化后再用“,”连接起来。

所有安全的JSON值(JSON-safe)都可以使用JSON.stringify(...)字符串化。安全的JSON值是指能够呈现为有效JSON格式的值。

不安全的JSON值:undefined、function、symbol和包含循环引用的对象都不符合JSON结构标准,支持JSON的语言无法处理它们。

JSON.stringify(...)在对象中遇到undefined、function、symbol时会自动将其忽略,在数组中则会返回null(以保证单元位置不变)。

如果对象中定义了toJSON()方法,JSON字符串化时就会首先调用该方法,然后用它的返回值来进行序列化。

如果要对含有非法JSON值的对象进行字符串化,或者对象中某些值无法被序列化时,就需要定义toJSON()方法来返回一个安全的JSON值。

toJSON()返回的应该是一个适当的值,可以是任何类型,然后再由JSON.stringify()对其进行字符串化。也就是说,toJSON()应该返回一个能够被字符串化的安全的JSON值,而不是返回一个JSON字符串。

我们可以向JSON.stringify(...)传递一个可选参数replacer,它可以是数组或是函数,用来指定对象序列化过程中哪些属性应该被处理,哪些应该被排除。如果replacer是一个数组,那么它会对对象本身调用一次,然后对对象中的每个属性各调用一次,每次传递两个参数,键和值。如果要忽略某个键就返回undefined,否则返回指定的值。

JSON.stringify(...)还有一个可选参数space,用来指定缩进格式。

  • 字符串、数字、布尔值和null的JSON.stringify(...)规则与toString基本相同。
  • 如果传递给JSON.stringify(...)的对象中定义了toJSON()方法,那么该方法会在字符串化前调用,以便将对象转换为安全的JSON值。

JavaScript中的值可以分为两类:

  • 可以被强制类型转换为false的值
  • 其他(被强制类型转换为true的值)

假值

  • undefined
  • null
  • false
  • +0、-0、NaN
  • ""

假值的布尔强制类型转换结果为false。

解析允许字符串中含有非数字字符,解析按从左到右的顺序,如果遇到非数字字符就停止。而转换不允许出现非数字字符,否则会失败并返回NaN。

一元运算符 ! 显示地将值强制类型转换为布尔值,但是它同时还将真值反转为假值(或者将假值转为真值)。所以显示强制类型转换为布尔值最常用的方法是 !!,因为第二个 ! 会将结果反转回原值。 

ES6允许符号到字符串的显示强制类型转换 ,然而隐式强制类型转换会产生错误,符号不能够被强制类型转换为数字(显式和隐式都会产生错误),但可以被强制类型转换为布尔值(显式和隐式结果都是true)。

常见误区:==检查值是否相等;===检查值和类型是否相等;

正确解释:==允许在相等比较中进行强制类型转换,而===不允许。

  • 如果Type(x)是数字,Type(y)是字符串,则返回x == ToNumber(y)的结果。
  • 如果Type(x)是字符串,Type(y)是数字,则返回ToNumber(x) == y的结果。
  • 如果Type(x)是布尔类型,则返回ToNumber(x) == y的结果。
  • 如果Type(y)是布尔类型,则返回x == toNumber(y)的结果。

了解超过一个运算符是表达式的执行顺序,这些规则被称为“运算符优先级”。

&&运算符优先于||执行,而且执行顺序并非我们所设想的从左到右。 而||的优先级又高于? : 。

如果运算符优先级/关联规则能够令代码更简洁就是用运算符优先级/关联规则;如果( )有助于提高代码可读性,就是用( )。

finally中的代码总会在try之后执行,如果有catch的话则在catch之后执行。也可以将finally中的代码看做一个回调函数,即无论出现什么情况最后一定会被调用。

在函数中省略return的结果和return;即return undefined;是一样的,但是在finally中省略return则会返回前面的return设定的返回值。

case表达式的匹配算法与===相同。

posted @ 2020-07-09 21:30  671_MrSix  阅读(137)  评论(0编辑  收藏  举报