2数据类型

一、数据类型概述

重学JavaScript基础!!之前跟着视频学习,稀里糊涂的,还是看文档好一些。

1、简介、

  • 数值(number):整数和小数
  • 字符串(string):文本
  • 布尔值(boolean):truefalse
  • undefined:表示未定义或不存在
  • null:表示空值;null是object的一种特殊值,通常用来表示未知空对象
var a = null
// 操作...
a = () => {}
  • 对象:各种值的组成集合。其中对象分为三类:
 - 狭义的对象
 - 数组
 - 函数:JavaScript把函数作为一种数据类型,可赋值给变量。(函数式编程)

2、typeof运算符

JavaScript有三种方法,可以确定一个值是声明类型。

  • typeof
typeof 123 // number
typeof '123' // string
typeof false // boolean
typeof undefined //undefined
function fn () {}
typeof fn // function

typeof null // object
typeof window // object
typeof {} // object
typeof [] // object

  • instanceof
// instanceof可以区分数组和对象
console.log([] instanceof Array) // true
console.log({} instanceof Array) // false
  • Object.prototype.toString

二、null、undefined、布尔值

1、null和undefined

  • 转为Boolean类型时,两者都是false
console.log(Boolean(null)) // false
console.log(Boolean(undefined)) // false
  • 使用==运算符,两值是相等的
if (null == undefined) { // true
  console.log('null == undefined')
}
  • null表示一个空对象,转为number为0undefined为无定义的原始值,转为number为NaN
console.log(Number(null)); // 0
console.log(Number(undefined)); // NaN

2、布尔值

JavaScript如果预期某个位置应该是布尔值,则该位置现有的值会自动转换为布尔值。

转换规则:下面6个值会被转换为false,其余值都为true

 - 0
 - NaN
 - ''
 - false
 - nudefined
 - null

三、数值

1、整数与浮点数

在JavaScript内部,所有数字都是以64位浮点数形式存储的。也就是说,JavaScript底层没有整数,所有数字都是小数。
整数部分运算,JavaScript会把64位浮点数转换为32位整数。

1 === 1.0 // true

由于浮点数不是精确的值,所以在进行小数比较和运算需特别小心。

0.1 + 0.2 === 0.3 // false

0.3 / 0.1 // 2.9999999999999996

(0.3 - 0.2) === (0.2 - 0.1) // false
// 0.09999999999999998 !== 0.1

2、数值精度和范围

2.1、数值精度:

国际IEEE754,JavaScript浮点数的64个二进制位,从左边开始,依次为:

  • 第1位:符号位,0表示正数,1表示负数;
  • 第2位 ~ 第12位(共11位)表示指数部分,指数部分的值在0到2047之间,不包含两个端点。
  • 第13位 ~ 第64位(共52位)表示小数部分(即有效数字)
二进制数:(1)^符号位 * 1.xx...xx * 2^指数部分
由于指数部分的值在(0,2047)范围内,所以小数部分第一位默认为1,不保存在64为二进制数中,
所以小数部分最多能存储到53位二进制数。

2.2、数值范围:

Number.MAX_VALUE // 1.7976931348623157e+308
Number.MIN_VALUE // 5e-324
  • 数值大于等于2的1024次方就会发生“正向溢出”,JavaScript无法表示这么大的数,就会返回Infinity
Math.pow(2, 1024) // Infinity
  • 数值小于等于2的-1075次方就会发生“负向溢出”,JavaScript无法表述这么小的数,就会直接返回0
Math.pow(2, -1075) // 0

3、数值的表示法

 var a = 22 // 十进制表示
a = 0xFF // 十六进制
// 科学计数法允许字母e或E的后面跟着一个整数,表示这个数的指数部分。
a = 123e3 // 科学计数法123000
a = 123e-3 // 科学计数法0.123
a = 3.1E+3 // 科学计数法3100
a = -3.1E+3 // 科学计数法-3100

以下两种情况JavaScript会自动将数值转为科学计数法表示,其余情况都将使用字面形式直接表示。

  • 小数点前的数字多于21位
  • 小数点后的0超过5位

4、数值的进制

使用字面量表示一个数值时,JavaScript提供四种进制:

  • 二进制:有前缀0b0B的数值。
  • 八进制:有前缀0o0O的数值,或者有前导0、且只用到0-7的八个阿拉伯数字的数值。
  • 十进制:如果数字前面出现0会被视为八进制,若0后面的数字为89时,会被视为十进制数。
前导0表示八进制,处理时很容易造成混乱。
ES5 的严格模式和 ES6,已经废除了这种表示法,
但是浏览器为了兼容以前的代码,目前还继续支持这种表示法。
  • 十六进制:有前缀0x0X的数值。

默认情况下,JavaScript会将二进制、八进制、十六进制转换为十进制数表示。若出现不属于该进制的数字时,会报错。

5、特殊数值

5.1、正零和负零

区别:

  • 64位浮点数的符号位不一样,但它们是等价的。
+0 // 0
-0 // 0
(+0).toString() // '0'
(-0).toString() // '0'
-0 === +0 // true
-0 === 0  // true
+0 === 0  // true
  • 做分母时返回的值是不相等的。
(1 / -0) === (1 / +0) // false
(1 / -0) // -Infinity
(1 / +0) // Infinity

5.2、NaN

NaN是JavaScript的特殊值,表示”非数字“(Not a Number);主要出现在字符串转数字出错的场合。

NaN不是独立的数据类型,是number类型中的一个特殊值。

typeof NaN // number
5 - 'x' // NaN

// 一些数学函数运算也会得到NaN
Math.acos(2) // NaN
Math.log(2) // NaN
Math.sqrt(2) // NaN

// 0除以0也会得到NaN
0 / 0 //  NaN

运算规则:

  • (1)、NaN不等于任何值,包括它本身
NaN === NaN // false
  • (2)、数组的indexOf方法内部使用的是严格相等运算符,所以该方法对NaN不成立
[NaN].indexOf(NaN) // 结果位-1
  • (3)、布尔值运算时被当作false
Boolean(NaN) // false
  • (4)、NaN与任何数运算,得到的都是NaN
NaN + 3 // NaN
NaN - 3 // NaN
NaN * 3 // NaN
NaN / 3 // NaN
  • (5)、NaN与其他类型的值运算
// string
var a = NaN + '12' // 字符串拼接:NaN12
a = NaN - '12' // NaN,与字符串乘法、除法运算也是NaN
a = '12' - NaN // NaN

// boolean
a = NaN - false // NaN
a = NaN - true // NaN

// 与null、undefined加减乘除都能得到NaN
a = null + NaN // NaN
a = undefined + NaN // NaN

5.3、Infinity-Infinity运算规则

运算规则

Infinity === -Infinity // false

6、与数值相关的全局方法

6.1、parseInt()

parseInt(x, base):将字符串转为数字。

x:待解析的字符串

base:可选参数,默认为10;2~36之间的整数,表示被解析的值的进制。

  • (1)、自动去除头部空格,若遇到不能转为数字的字符(包括小数点、空格),会停止转换,将返回已转换好的部分。
parseInt('   123.89  6 ') // 123
  • (2)、如果parseInt()的参数不是字符集,则先转为字符串再转换为整数。如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回NaN。

也就意味着,truefalsenullundefined将先转为字符串,再进行数值转换。

parseInt(123)
// 等同于
parseInt('123')
parseInt('abc') // NaN
parseInt(null) // NaN
parseInt('.3') // NaN
parseInt('') // NaN
parseInt('+') // NaN
parseInt('+1') // 1

所以parseInt()的返回值只有两种结果:数字、NaN

6.2、parseFloat()

parseFloat():将字符串转换为浮点数,自动去除头部空格;若字符串符合科学计数法,则会自动转换。

parseFloat('314e-2') // 3.14
// 其余的运算和parseInt()大同小异

6.3、isNaN()

isNaN()方法用来判断一个number类型的值是否为NaN。

如果传入其他类型的值,自动会被转为数值(通过Number()方法转换),再做判断

isNaN(123) // false
isNaN('123') // false
isNaN(NaN) // true
isNaN('sada') // true
isNaN(true) // false

特殊的:

isNaN(['xzy']) // true
// 等同于
isNaN(Number(['xzy'])) // true

但是,对于空数组和只有一个数值成员的数组,isNaN返回false。

isNaN([]) // false
isNaN([123]) // false
isNaN(['123']) // false

因此,使用isNaN之前,最好判断一下数据类型。

function myIsNaN(value) {
  return typeof value === 'number' && isNaN(value);
}

判断NaN更可靠的方法是,利用NaN为唯一不等于自身的值的这个特点,进行判断。

function myIsNaN(value) {
return value !== value;
}

6.4、isFinite()

isFinite方法返回一个布尔值,表示某个值是否为正常的数值。

若传入其他类型的值将会被Number()转换为number类型在做判断

isFinite(Infinity) // false
isFinite(-Infinity) // false
isFinite(NaN) // false
isFinite(undefined) // false
isFinite(null) // true
isFinite(-1) // true

四、字符串

1、length属性

length属性返回字符串的长度

var a = 'dsckjjnc'
console.log(a.length) // 8

2、字符集

JavaScript引擎内部所有字符都是用Unicode表示。

var a = '/u00A9';
console.log(a) // @版权符号

3、base64转码

base64是一种编码方法 ,可以将任意值转换为0-9A-Za-z+/这64个字符组成的可打印字符。

使用它的目的不是加密,而是为了不出现特殊字符,简化程序处理。

使用场景:

  • 文本中包含一些不可打印的字符,比如ASCII吗0到31的符号都无法打印出来;这时可以使用base64编码,把他们转换为可以打印的编码。

  • 需要以文本格式传递二进制数据时,可以使用base64编码。

JavaScript原生提供两个base64方法:

  • btoa():任意值转为base64编码。
  • atob():base64编码转为原来的值。

注意:这两个方法不适合ASCII码的字符,会报错

btoa('你好') // 报错

若需要将 ASCII码字符串转为base64编码,需要先转码,再进行base64编码。

// 编码
function b64Encode(str) {
    return btoa(encodeURIComponent(str)) // 转码,再base64编码
}
// 解码
function b64Decode(str) {
    return DecodeURIComponent(atob(str)) // 先base64解码,再转码
}

五、对象

1、生成方法

对象是一组“键值对”(key-value)的组合,是一种无序的符合数据组合。

var obj = {
    key: value
}

2、键名、键值

键名(属性):所有键名都是字符串(ES6引入Symbol值也可以作为键名),所以键名加不加引号都是可以的。

如果键名是数值,会被自动转为字符串。

var obj = {
    1000: 'value'
}
obj['1000'] // value
obj[1000] // value

如果键名不符合标识符的的条件,则必须使用引号。

var obj = {
    '1saj': '数字开头的key',
    'h m': 'key中有空格',
    'h+m': '可以中包含运算符'
}

键值(属性值):键值可以是任何数据类型。

如果一个属性的值为函数,通常把这个属性称为方法,它可以像函数那样调用。

3、属性的操作

3.1、属性的读取和赋值

  • 使用点运算符

  • 使用方括号运算符

    var obj = {
        name: 'nico'
    }
    // 读取属性
    obj.name // nico
    obj['name'] // nico
    // 属性赋值
    obj.name = 'allen' // allen
    obj['name'] = 'jack' // jack
    

3.2、属性的查看和删除

  • 查看:查看一个对象本身的所有属性,可以使用Object.keys()方法。该方法返回一个数组;若对象为空对象,则返回一个空数组。
var obj = {
    name: 'nico',
    age: 18
}
Object.keys(obj) // [ 'name', 'age' ]
  • 删除:delete命令用于删除对象本身的属性。

    删除成功后返回true;删除对象上一个不存在的属性也会返回true

    若属性不可删除,则返回false

    delete只能删除对象本身的属性,无法删除继承的属性。

var obj = {
    name: 'nico'
}
console.log(delete obj.name) // true
delete obj.height // true

var objExtend = Object.defineProperty({}, 'p', {
    value: 123,
    configureable: false // 设置该属性不可改变
})
delete objExtend.p // true
console.log(objExtend.p) // 123,属性并没有被删除,依然存在。

3.3、属性是否存在

in运算符用于检查对象是否包含某个属性(检查的是键名,不是键值)。但它不能识别哪些属性是自身的,哪些是继承来的。可以使用对象的方法hasOwnProperty判断属性是否为对象自身的属性。

var obj = Object.defineProperty({}, 'name', { value: 'nico'})
obj.age = 18
console.log(obj.hasOwnProperty('name')) // true
console.log(obj.hasOwnProp1erty('age')) // true

console.log('name' in obj) // true
console.log('age' in obj) // true

3.4、属性的遍历

for...in循环用来遍历一个对象的全部属性

var obj = {
    name: 'nico',
    age: 19
}
for(let key in obj) {
    console.log('键名:' + key)
    console.log('键值:' + obj[key])
}
// 键名:name
// 键值:nico
// 键名:age
// 键值:19

注意:

  • for...in不仅遍历自身属性,还遍历继承来的属性。

  • 它遍历对象上所有可遍历的属性(enumberable),会跳过不可遍历的属性。

    如果只想遍历对象自身的属性,需结合对象的hasOwnProperty()方法来判断实现。

    var obj = {
        name: 'nico',
        age: 19
    }
    for(let key in obj) {
        if (obj.hasOwnProperty(key)) {
            console,log(key)
        }
    }
    // name
    // nico
    

4、with语句

with语句的作用是操作同一对象的多个属性时,提供一些书写的方便

with (对象) {
    语句;
}
var obj = {
    name: '',
    age: 0
}
// 操作对象属性
with(obj) {
    name: 'nico',
    age:20
}
// 等同于
obj.name = 'nico'
obj.age = 23

注意:如果with区块内部有变量的赋值操作,必须是当前对象已存在的属性,否则会创建一个当前作用域的全局变量。

这是因为with区块没有改变作用域,区块内部任然是当前作用域,所以with语句绑定的对象不是很明确。建议不使用with

语句。

let obj = {
    name: 'nico',
    weight: '60KG'
}
with (obj) {
    name = 'allen'
    age = 18
}
console.log(obj.age) // undefined
conosle.log(age) // '60KG'
var x = 123
with (obj) {
    let x = ''
    console.log(x) // with无法判断x是区块内的变量x还是当前环境的变量x
}

六、函数

1、概述

JavaScript 语言将函数看作一种值,与其它值(数值、字符串、布尔值等等)地位相同。凡是可以使用值的地方,就能使用函数。比如,可以把函数赋值给变量和对象的属性,也可以当作参数传入其他函数,或者作为函数的结果返回。函数只是一个可以执行的值,此外并无特殊之处。

1.1、函数的声明

  • (1)、function命令

  • (2)、函数表达式

  • (3)、Function构造函数:此种方式不直观,几乎不使用。

    function fun1 () {}
    const fun2 = function() {}; // 需要加分号用来结束语句
    const fun3 = new Function('x', 'y', 'return x + y')
    // 等同于
    function fun3(x, y) {
        return x + y
    }
    
    // 特殊的:该函数名`x`只在函数体内部有效,在函数体外部无效。
    const f = function x() {}
    // 这种写法的用处有两个,一是可以在函数体内部调用自身;二是方便除错(除错工具显示函数调用栈时,将显示函数名,而不再显示这里是一个匿名函数)。
    

1.2、函数的重复声明

如果同一个函数被多次声明,后面的声明会覆盖前面的声明。

JavaScript中由于函数名的提升,第一次的函数声明在任何时候都是无效的!

1.3圆括号运算符、return语句和递归

  • 圆括号运算符:调用函数时,要使用圆括号运算符;圆括号中可以加入函数的参数。

  • return语句JavaScript引擎遇到return语句就会返回return语句后面的表达式,不会执行后续的代码;如果return语句后面没有表达式,,该函数不会返回任何值,或者说返回undefined

  • 递归:函数可以调用自身。

    function fib(num) {
      if (num === 0) return 0;
      if (num === 1) return 1;
      return fib(num - 2) + fib(num - 1);
    }
    
    fib(6) // 8
    

1.4、函数名的提升

JavaScript引擎将函数名视同变量名,所以采用function声明函数时,整个函数会像变量声明一样,被提升到代码头部。

fun() // 不会报错
function fun () {}

使用var定义函数表达式

fun() // TypeError: undefined is not a function
var fun = () => {}
// 上面代码等同于
var fun; // 先进行变量提升,在进行赋值操作
fun();
fun = () => {}

变量提升函数提升与函数重复声明:

var fun = () => {
    console.log(1)
}
function fun() {
    console.log(2)
}
fun() // 1

// 解析: 
// 1、先进行变量提升和函数提升
// var fun;
// function fun() {
//      console.log(2)
// }
// 2、最后进行变量赋值操作。

2、函数的属性和方法

2.1、name属性和length属性

  • 函数的name属性返回函数的名字
function fun1() {}
fun1.name // fun1

const fun2 = () => {}
fun2.name // fun2

// 特殊的
const fun3 = function x() {}
fun3.name // x
  • 函数的length属性

    函数的length属性返回函数预期的参数个数。不管调用函数时传入多少个参数,length属性总为定义函数时的参数个数。

    function fun(x, y) {}
    fun.length // 2
    

2.2、toString()方法

函数的toString()方法返回函数源码字符串

const fun = () => {}
console.log(fun.toString()) // () => {}

// 对于JavaScript原生函数,将返回 function Number() { [native code] }
console.log(Number.toString()) // function Number() { [native code] }

3、函数的作用域

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 227,572评论 6 531
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 98,071评论 3 414
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 175,409评论 0 373
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 62,569评论 1 307
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,360评论 6 404
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 54,895评论 1 321
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 42,979评论 3 440
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,123评论 0 286
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,643评论 1 333
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,559评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,742评论 1 369
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,250评论 5 356
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 43,981评论 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,363评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,622评论 1 280
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,354评论 3 390
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,707评论 2 370

推荐阅读更多精彩内容