JS基础


本文总结于: 侯策《前端开发核心知识进阶》

JavaScript 类型及其判断

JavaScript 具有七种内置数据类型,它们分别是:null、undefined、boolean、number、string、object、symbol,其中object 类型又具体包含了 function、array、date 等

对于这些类型的判断,我们常用的方法有:typeof、instanceof、Object.prototype.toString、constructor

typeof

使用 typeof 可以准确判断出除 null 以外的基本类型,以及 function 类型、symbol 类型;null 会被 typeof 判断为 object。

typeof 5 // "number"
typeof 'lucas' // "string"
typeof undefined // "undefined"
typeof true // "boolean"
typeof null // "object"
const foo = () => 1
typeof foo // "function"
const foo = {}
typeof foo // "object"
const foo = []
typeof foo // "object"
const foo = new Date()
typeof foo // "object"
const foo = Symbol("foo") 
typeof foo // "symbol"

instanceof

function Person(name) {
    this.name = name
}
const p = new Person('lucas')

p instanceof Person
// true

Object.prototype.toString

console.log(Object.prototype.toString.call(1)) 
// [object Number]

console.log(Object.prototype.toString.call('lucas')) 
// [object String]

console.log(Object.prototype.toString.call(undefined)) 
// [object Undefined]

console.log(Object.prototype.toString.call(true)) 
// [object Boolean]

console.log(Object.prototype.toString.call({})) 
// [object Object]

console.log(Object.prototype.toString.call([])) 
// [object Array]

console.log(Object.prototype.toString.call(function(){})) 
// [object Function]

console.log(Object.prototype.toString.call(null)) 
// [object Null]

console.log(Object.prototype.toString.call(Symbol('lucas'))) 
// [object Symbol]

constructor

var foo = 5
foo.constructor
// ƒ Number() { [native code] }

var foo = 'Lucas'
foo.constructor
// ƒ String() { [native code] }

var foo = true
foo.constructor
// ƒ Boolean() { [native code] }

var foo = []
foo.constructor
// ƒ Array() { [native code] }

var foo = {}
foo.constructor
// ƒ Object() { [native code] }

var foo = () => 1
foo.constructor
// ƒ Function() { [native code] }

var foo = new Date()
foo.constructor
// ƒ Date() { [native code] }

var foo = Symbol("foo") 
foo.constructor
// ƒ Symbol() { [native code] }

var foo = undefined
foo.constructor
// VM257:1 Uncaught TypeError: Cannot read property 'constructor' of undefined
    at <anonymous>:1:5

var foo = null
foo.constructor
// VM334:1 Uncaught TypeError: Cannot read property 'constructor' of null
    at <anonymous>:1:5

对于 undefined 和 null,如果尝试读取其 constructor 属性,将会进行报错。并且 constructor 返回的是构造函数本身,一般使用它来判断类型的情况并不多见。

JavaScript 类型及其转换

JavaScript 是一种弱类型或者说动态语言。这意味着你不用提前声明变量的类型,在程序运行过程中,类型会被自动确定。

console.log(1 + '1')
// 11

console.log(1 + true)
// 2

console.log(1 + false)
// 1

console.log(1 + undefined)
// NaN

console.log('lucas' + true)
// lucastrue

当使用 + 运算符计算 string 和其他类型相加时,都会转换为 string 类型;其他情况,都会转换为 number 类型,但是 undefined 会转换为 NaN,相加结果也是 NaN

当使用 + 运算符计算时,如果存在复杂类型,那么复杂类型将会转换为基本类型,再进行运算

对象在转换基本类型时,会调用该对象上 valueOf 或 toString 这两个方法,该方法的返回值是转换为基本类型的结果

JS中Number()、parseInt()和parseFloat()

三者的作用:
Number(): 可以用于任何数据类型转换成数值;
parseInt()、parseFloat(): 专门用于把字符串转换成数值;

Number()

(1)如果是Boolean值,true和false将分别转换为1和0。
(2)如果是数字值,只是简单的传入和返回。
(3)如果是null值,返回0。
(4)如果是undefined,返回NaN。
(5)如果是字符串,遵循下列规则:

如果字符串截去开头和结尾的空白字符后,不是纯数字字符串,那么最终返回结果为NaN。
如果是字符串中只包含数字(包括前面带正号或负号的情况),则将其转换为十进制数值,即“1”变成1,“123”会变成123,而“011”会变成11(前导的零被忽略了);
如果字符串中包含有效的浮点格式,如“1.1”,则将其转换为对应的浮点数值(同样也会忽略前导零);
如果字符串中包含有效的十六进制格式,例如”0xf”,则将其他转换为相同大小的十进制整数值;
如果字符串是空的(不包含任何字符),则将其转换为0;
如果字符串中包含除上述格式之外的字符,则将其他转换成NaN.
(6)如果是对象,则调用对象的valueOf()方法,然后依照前面的规则转换返回的值。如果转换的结果是NaN,则调用的对象的toString()方法,然后再次依照前面的规则转换返回的字符串值。

var num1=Number("Hello World");  //NaN

var num2=Number("");             //0

var num3=Number("000011");       //11

var num4=Number(true);           //1

var num5=Number("num123")       //NaN

parseInt()

parseInt()函数可以将字符串转换成一个整数,与Number()函数相比,parseInt()函数不仅可以解析纯数字字符串,也可以解析以数字开头的部分数字字符串(非数字部分字符串在转换过程中会被去除)。
(1)如果第一个字符不是数字字符或者负号,parseInt()就会返回NaN; 也就是说,用parseInt()转换空字符串会返回NaN。
(2)如果第一个字符是数字字符,parseInt()会继续解析第二个字符,直到解析完所有后续字符或者遇到了一个非数字字符。
(3)如果字符串以”0x”开头且后跟数字字符,就会将其当作一个十六进制整数。
(4)如果字符串以”0”开头且后跟数字字符,就会将其当作一个八进制整数。
(5)parseInt()函数增加了第二参数用于指定转换时使用的基数(即多少进制)。
(6)当parseInt()函数所解析的是浮点数字符串时,取整操作所使用的方法为“向下取整”。

var num1=parseInt("num123");    //NaN
var num2=parseInt("");          //NaN
var num3=parseInt("123.45")     //123
var num4=parseInt("101010",2)   //42
var num5=parseInt("123num")     //123
var num6=parseInt("0xff")       //255

parseFloat( )

与parseInt()一样,parseFloat()也可以解析以数字开头的部分数字字符串(非数字部分字符串在转换过程中会被去除)。与parseInt()不同的是,parseFloat()可以将字符串转换成浮点数;但同时,parseFloat()只接受一个参数,且仅能处理10进制字符串。
(1)字符串中的第一个小数点是有效的,而第二个小数点就是无效的了,因此它后面的字符串将被忽略。
(2)如果字符串包含的是一个可解析为整数的数(没有小数点,或者小数点后面都是零),parseFloat()会返回整数。

var num1=parseFloat("1234blue");    //1234

var num2=parseFloat("0xA");         //0

var num3=parseFloat("0908.5");      //908.5

var num4=parseFloat("3.125e7");     //31250000

var num5=parseFloat("123.45.67")    //123.45

var num6=parseFloat("")             //NaN

var num7=parseFloat("num123")       //NaN

JS中的NAN

NAN概念

NaN 即 Not a Number ,不是一个数字。 在 JavaScript 中,整数和浮点数都统称为 Number 类型 。除此之外,Number 类型还有一个很特殊的值,即 NaN 。它是 Number 对象上的一个静态属性,可以通过 Number.NaN 来访问 。

在 ECMAScript v1 和其后的版本中,还可以用预定义的全局属性 NaN 代替 Number.NaN 。

console.log(Number.NaN); // NaN
console.log(NaN); // NaN

NAN的产生

表达式计算

一个表达式中如果有减号 (-)、乘号 (*) 或 除号 (/) 等运算符时,JS 引擎在计算之前,会试图将表达式的每个分项转化为 Number 类型(使用 Number(x) 做转换)。如果转换失败,表达式将返回 NaN 。

100 - '2a'; // NaN
'100'/ '20a'; // NaN
'20a'* 5 ; // NaN
undefined - 1; // NaN, Number(undefined) == NaN
[] * 20 ; // 0, Number([]) == 0
null- 5; // -5, Number(null) == 0

而 加号 (+) 不会将其两边的变量转化为 Number 类型,这是因为JS表达式的执行顺序是按照运算符的优先级从左到右依次进行的,如果加号 (+) 两边的变量都是 Number 类型时,才会做数字相加运算,如果其中有一个变量是字符串,则会将两边都作为字符串相加。

类型转换

直接使用 parseInt,parseFloat 或 Number 将一个非数字的值转化为数字时,表达式返回 NaN 。

'abc'- 3   // NaN
parseInt('abc')  // NaN
parseFloat('abc') // NaN
Number('abc')    // NaN
Number('123abc'); // NaN
parseInt('123abc'); // 123
parseInt('123abc45'); // 123
parseFloat('123.45abc');// 123.45

Number 转换的是整个值,而不是部分值;parseInt 和 parseFloat 只转化第一个无效字符之前的字符串。 另外,一元加操作符也可以实现与 Number 相同的作用。

因此,当一个字符串不能被 Number、parseInt 或 parseFloat 成功转换时,就返回 NaN,表示该字符串无法被识别为数字类型,这是一个异常状态,并不是一个确切的值。

isNaN

isNaN() 是一个全局方法,它的作用是检查一个值是否能被 Number() 成功转换 。 如果能转换成功,就返回 false,否则返回 true 。

isNaN(NaN)    // true 不能转换
isNaN('123')   // false 能转换
isNaN('abc')    // true 不能转换
isNaN('123ab')   // true 不能转换
isNaN('123.45abc') // true 不能转换

另外,ES6 在 Number 对象上也提供了 isNaN() 方法,和全局方法 isNaN() 不同的是,它用于判断某个值本身是否为 NaN,而不需要进行类型转换。

Number.isNaN('123'); // false 本身不是NaN
Number.isNaN('abc'); // false 本身不是NaN
Number.isNaN(NaN); // true 本身是NaN

JavaScript 函数参数传递

let foo = 1
const bar = value => {
    value = 2
    console.log(value)
}
bar(foo)
console.log(foo) 
//2 1
let foo = {bar: 1}
const func = obj => {
    obj.bar = 2
    console.log(obj.bar)
}
func(foo)
console.log(foo)
//2 {bar: 2}

参数为基本类型时,函数体内复制了一份参数值,而不会影响参数实际值。如果函数参数是一个引用类型,当在函数体内修改这个引用类型参数的某个属性值时,将会对参数进行修改。因为这时候函数体内的引用地址指向了原来的参数。

cannot read property of undefined 问题解决方案

const obj = {
    user: {
        posts: [
            { title: 'Foo', comments: [ 'Good one!', 'Interesting...' ] },
            { title: 'Bar', comments: [ 'Ok' ] },
            { title: 'Baz', comments: []}
        ],
        comments: []
    }
}

验证对象每一个 key 的存在性。常见的处理方案:

&& 短路运算符进行可访问性嗅探

obj.user &&
obj.user.posts &&
obj.user.posts[0] &&
obj.user.posts[0].comments

|| 单元设置默认保底值

(((obj.user || {}).posts||{})[0]||{}).comments 

try…catch

var result
try {
    result = obj.user.posts[0].comments
}
catch {
    result = null
}

例题:

Can (a == 1 && a == 2 && a == 3) ever evaluate to true?

const a = {
    value: 1,
    toString: function () {
        return a.value++
    }
}
console.log(a == 1 && a == 2 && a == 3) // true

let value = 0
Object.defineProperty(window, 'a', {
    get: function() {
        return ++value
    }
})

console.log(a == 1 && a == 2 && a == 3) // true

参考资料:
https://blog.csdn.net/m0_38099607/article/details/72638678
https://www.cnblogs.com/onepixel/p/5281796.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值