六种数据类型
- 数值(number)
- 字符串(string)
- 布尔值(boolean)
- undefined
- null
- 对象(Object,复杂数据类型,object,array,function)
使用typeOf可以返回一个值的数据类型
检查一个没有声明的变量, null的类型为object(历史原因)
null 和 undefined
1、在if语句中二者都会转为fasle,==运算符甚至报告两者相等。 2、null为数字的时候自动转为0(历史原因)undefined转为数值为NaN 3、调用函数的时候某个参数没有设置任何值,就可以传入null 4、 undefined、null、false、0、NaN、""、'' 都会转为fasle
数值
整数和浮点数
所有数字都是以64位浮点数形式储存,即使整数也是如此 JavaScript 语言的底层根本没有整数,所有数字都是小数(64位浮点数)。容易造成混淆的是,某些运算只有整数才能完成,此时 JavaScript 会自动把64位浮点数,转成32位整数,然后再进行运算
数值精度
- 第1位:符号位,0表示正数,1表示负数
- 第2位到第12位(共11位):指数部分
- 第13位到第64位(共52位):小数部分(即有效数字)
Number.MAX_VALUE // 1.7976931348623157e+308
Number.MIN_VALUE // 5e-324
注意:NaN不是独立的数据类型,而是一个特殊数值,它的数据类型依然属于Number
转换
1、parseInt方法用于将字符串转为整数。
- 如果parseInt的参数不是字符串,则会先转为字符串再转换。
- 如果parseInt的参数不是字符串,则会先转为字符串再转换。
- 字符串转为整数的时候,是一个个字符依次转换,如果遇到不能转为数字的字符,就不再进行下去,返回已经转好的部分。
- 如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回NaN。
2、parseFloat()
- parseFloat方法用于将一个字符串转为浮点数。
- 如果字符串符合科学计数法,则会进行相应的转换。
- 如果字符串包含不能转为浮点数的字符,则不再进行往后转换,返回已经转好的部分。
- parseFloat方法会自动过滤字符串前导的空格。
- 如果参数不是字符串,则会先转为字符串再转换。
- 如果字符串的第一个字符不能转化为浮点数,则返回NaN。
3、 isNaN()
- isNaN方法可以用来判断一个值是否为NaN。
- isNaN只对数值有效
- 对于空数组和只有一个数值成员的数组,isNaN返回false。(原因是这些数组能被Number函数转成数值)
- 判断NaN更可靠的方法是,利用NaN为唯一不等于自身的值的这个特点,进行判断。
//判断一
function myIsNaN(value) {
return typeof value === 'number' && isNaN(value);
}
//判断二
function myIsNaN(value) {
return value !== value;
}
4、isFinite()
isFinite方法返回一个布尔值,表示某个值是否为正常的数值。
字符串
如果长字符串必须分成多行,可以在每一行的尾部使用反斜杠。
如果想输出多行字符串,有一种利用多行注释的变通方法。
字符串和数组
- 字符串可以被视为字符数组,因此可以使用数组的方括号运算符,用来返回某个位置的字符(位置编号从0开始)。
- 如果方括号中的数字超过字符串的长度,或者方括号中根本不是数字,则返回undefined。
- length属性返回字符串的长度,该属性也是无法改变的。
- JavaScript 的单位字符长度固定为16位长度,即2个字节。
对象
概述
- 键名
- 对象的所有键名都是字符串
- 如果键名是数值,会被自动转为字符串。
- 如果键名不符合标识名的条件(比如第一个字符为数字,或者含有空格或运算符),且也不是数字,则必须加上引号,否则会报错。
- 属性可以动态创建,不必在对象声明时就指定。
- 对象的引用
- 如果不同的变量名指向同一个对象,那么它们都是这个对象的引用,也就是说指向同一个内存地址。修改其中一个变量,会影响到其他所有变量。
- 如果取消某一个变量对于原对象的引用,不会影响到另一个变量
- 表达式还是语句
- 无法确定是对象还是代码块,一律解释为代码块。
- 如果要解释为对象,最好在大括号前加上圆括号。因为圆括号的里面,只能是表达式,所以确保大括号只能解释为对象。
属性操作
- 属性读取
- 一种是使用点运算符,还有一种是使用方括号运算符。
- 如果使用方括号运算符,键名必须放在引号里面,否则会被当作变量处理。
- 数字键可以不加引号,因为会自动转成字符串。(数值键名不能使用点运算符(因为会被当成小数点),只能使用方括号运算符。)
var foo = 'bar';
var obj = {
foo: 1,
bar: 2
};
obj.foo // 1
obj[foo] // 2 如果foo不加引号,表示变量值'bar'
- 属性赋值
- 点运算符和方括号运算符,不仅可以用来读取值,还可以用来赋值。 *任意时刻新增属性,没必要在定义对象的时候,就定义好属性。
- 属性查看
查看一个对象本身的所有属性,可以使用Object.keys方法。
var obj = {
key1: 1,
key2: 2
};
Object.keys(obj);
// ['key1', 'key2']
- 属性删除
- delete命令用于删除对象的属性,删除成功后返回true。
- 删除一个不存在的属性,delete不报错,而且返回true。
- delete命令会返回false,那就是该属性存在,且不得删除。
- delete命令只能删除对象本身的属性,无法删除继承的属性
- 属性是否存在
- in运算符用于检查对象是否包含某个属性(注意,检查的是键名,不是键值),如果包含就返回true,否则返回false。它的左边是一个字符串,表示属性名,右边是一个对象。
- 不能识别哪些属性是自身的还是继承的,要使用hasOwnProperty判断一下
- 属性遍历
- for...in循环用来遍历一个对象的全部属性。
- 它遍历的是对象所有可遍历(enumerable)的属性,会 。
- 它不仅遍历对象自身的属性,还遍历继承的属性。
- 遍历自身的还是用 hasOwnProperty
- with
- 它的作用是操作同一个对象的多个属性时,提供一些书写的方便。
函数
概述
函数声明
- function命令(采用function命令声明函数时,整个函数会像变量声明一样,被提升到代码头部)
- 函数表达式(var fun = function(){};)
- Function构造函数
注意:
- 如果同一个函数被多次声明,后面的声明就会覆盖前面的声明。
- 调用函数时,要使用圆括号运算符。圆括号之中,可以加入函数的参数。
- 没有return 的话,返回undefined
- 凡是能使用值的地方都可以使用函数
函数的属性和方法
name属性
- 函数的name属性返回函数的名字。
- 如果是通过变量赋值定义的函数,那么name属性返回变量名。
- 如果变量的值是一个具名函数,那么name属性返回function关键字之后的那个函数名。真正的函数名还是f3,而myName这个名字只在函数体内部可用。
var f3 = function myName() {};
f3.name // 'myName'
length属性
函数定义之中的参数个数。
toString()
函数的toString()方法返回一个字符串,内容是函数的源码。函数内部的注释也可以返回。
函数作用域
JavaScript 只有两种作用域:一种是全局作用域,变量在整个程序中一直存在,所有地方都可以读取;另一种是函数作用域,变量只在函数内部存在。
解释:
- 对于var命令来说,局部变量只能在函数内部声明,在其他区块中声明,一律都是全局变量。
- 函数内部也有变量提升
- 函数本身也是一个值,也有自己的作用域。它的作用域与变量一样,就是其声明时所在的作用域,与其运行时所在的作用域无关。
var a = 1;
var x = function () {
console.log(a);
};
function f() {
var a = 2;
x();
}
f() // 1
//函数体内部声明的函数,作用域绑定函数体内部。(构成了后面的闭包)
function foo() {
var x = 1;
function bar() {
console.log(x);
}
return bar;
}
var x = 2;
var f = foo();
f() // 1
参数
概述
- 参数省略(函数参数不是必需的,JavaScript 允许省略参数,函数的length属性与实际传入的参数个数无关,只反映函数预期传入的参数个数。)
- 传递方式(如果函数参数是复合类型的值(数组、对象、其他函数),传递方式是传址传递(pass by reference))
- 同名参数(取后面一个)
- arguments (在函数体内才能使用,arguments对象可以在运行时修改。修改arguments对象不会影响到实际的函数参数.注意:并不是数组但可以转换为数组,如下代码)
var args = Array.prototype.slice.call(arguments);
// 或者
var args = [];
for (var i = 0; i < arguments.length; i++) {
args.push(arguments[i]);
}
其他知识点
闭包
引入:
得到函数内的局部变量,只有通过变通方法才能实现。那就是在函数的内部,再定义一个函数。JavaScript 语言特有的"链式作用域"结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。 由于在 JavaScript 语言中,只有函数内部的子函数才能读取内部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。
作用
闭包的最大用处有两个,一个是可以读取外层函数内部的变量,另一个就是让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在。
立即调用:
function这个关键字既可以当作语句,也可以当作表达式。 JavaScript 规定,如果function关键字出现在行首,一律解释成语句。因此,引擎看到行首是function关键字之后,认为这一段都是函数的定义,不应该以圆括号结尾,所以就报错了。
(function(){ /* code */ }());
// 或者
(function(){ /* code */ })();
var i = function(){ return 10; }();
true && function(){ /* code */ }();
0, function(){ /* code */ }();
!function () { /* code */ }();
~function () { /* code */ }();
-function () { /* code */ }();
+function () { /* code */ }();
eval命令
eval命令接受一个字符串作为参数,并将这个字符串当作语句执行。 eval的本质是在当前作用域之中,注入代码 eval最常见的场合是解析 JSON 数据的字符串,不过正确的做法应该是使用原生的JSON.parse方法。 为了保证eval的别名不影响代码优化,JavaScript 的标准规定,凡是使用别名执行eval,eval内部一律是全局作用域。
数组
任何类型的数据,都可以放入数组。
数组本质属于特殊对象,typeOf 返回Object,Object.keys方法返回数组的所有键名。可以看到数组的键名就是整数0、1、2。
length属性
数组的length属性,返回数组的成员数量。length属性是可写的。如果人为设置一个小于当前成员个数的值,该数组的成员数量会自动减少到length设置的值。
in运算符
1、如果数组的某个位置是空位,in运算符返回false。
for in
for...in不仅会遍历数组所有的数字键,还会遍历非数字键。
数组的空位
当数组的某个位置是空元素,即两个逗号之间没有任何值,我们称该数组存在空位(hole)。数组的空位是可以读取的,返回undefined。使用delete命令删除一个数组成员,会形成空位,并且不会影响length属性
备注:
数组的某个位置是空位,与某个位置是undefined,是不一样的。如果是空位,使用数组的forEach方法、for...in结构、以及Object.keys方法进行遍历,空位都会被跳过。如果某个位置是undefined,遍历的时候就不会被跳过。
类似数组的对象
典型的“类似数组的对象”是函数的arguments对象,以及大多数 DOM 元素集,还有字符串。所以最好还是先将“类似数组的对象”转为真正的数组,然后再直接调用数组的forEach方法。