一、数据类型
1、 主要分为以下两种:
基本类型:指的是值保存在栈内存中的简单数据段;
如:null、undefined、boolean、number、string、symbol;
按值访问,直接访问值;
复制会在栈中创建一个新值,然后把值复制到为新变量分配的位置上。
值是不可变得,不能给基本类型添加属性和方法。
var person = 'jozo'; person.age = 22; person.method = function(){//...}; console.log(person.age); // undefined console.log(person.method); // undefined
引用类型:指的是那些值保存在堆内存中的对象
如object、闭包;(new 操作,就是在堆中去申请一个空间存储这个对象的实体本身)
按引用访问,需要先从栈中读取内存地址;然后找到保存在堆内的值;(对象堆空间不能直接访问)
复制的是存储在栈中的指针,即指针分配到新位置,而指针指向的堆内存的对象不变;
var a = {}; // a保存了一个空对象的实例 var b = a; // a和b都指向了这个空对象 a.name = 'jozo'; console.log(a.name); // 'jozo' console.log(b.name); // 'jozo' b.age = 22; console.log(b.age);// 22 console.log(a.age);// 22 console.log(a == b);// true
注:js数据结构
1、栈(stack)-----系统自动分配相对固定大小的内存空间,并由系统自动释放;栈空间是高地址向低地址拓展的数据结果,是连续的内存、运算速度比堆快
2、堆(heap) -----程序员自己通过 new
、malloc
等申请的空间,动态分配内存,内存大小不一,也不会自动释放(故内存泄漏几乎都在堆区发生,需要程序员手动去 free
或者 delete
)
3、其他:
js内存生命周期: 分配内存 -》 使用(读写)内容 -》释放、归还内存(局部变量的内存容易回收,全局变量难回收)
二、类型转换
1、类型转换分为两种:强制转换与隐式转换
1.1、显式转换
转换为数值类型:Number(mix)、parseInt(string,radix)、parseFloat(string) 转换为字符串类型:toString(radix)、String(mix) 转换为布尔类型:Boolean(mix)//!!等价于Boolean(mix)
注:parseInt可把二进制、八进制、十六进制或其他任何进制的字符串转换成整数(注意:parseInt是字符串转换成整数)
parseInt("10", 2); //2 parseInt("66", 8); //54 parseInt("10", 10); //10 parseInt("1234blue"); //1234 parseInt("0xA"); //10 parseInt("22.5"); //22 parseInt("blue"); //NaN
parseFloat
字符串转浮点数字
parseFloat("1234blue"); //1234.0 parseFloat("0xA"); //NaN parseFloat("22.5"); //22.5 parseFloat("22.34.5"); //22.34 parseFloat("0908"); //908 parseFloat("blue"); //NaN
toString() 方法,把数字转字符串转为二进制 八进制 十六进制字符串,, 不带参,就默认为10
(6).toString(2); //"110" (66).toString(8); //"102" (66).toString(16); //"42"
Object()方法,把原始值,根据它的类型,使用对应的构造函数,创建一个对象
Object(66); //数字对象,等于 new Number(66) Object("66"); //字符串对象,等于 new String("666") Object(true); //布尔对象, 等于 new Boolean(true) Object(null); //空对象,等于 new Object() Object(undefined); //空对象,等于 new Object()
1.2、隐式转换
下面我瞎写(别介意)的实例几乎包括了大部分弱类型转换的情况。
值 | 转数字 | 转字符串 | 转布尔值 | 实例 |
---|---|---|---|---|
undefined | NaN | “undefined” | false |
undefined+1=NaN !undefined+1=2 |
null | 0 | “null” | false | null+1=1 |
true | 1 | “true” | 不变 | true+true=2 |
false | 0 | “false” | 不变 | false+!false=1 |
0 | 不变 | “0” | false | 0+!0=1 |
-0 | 不变 | “0” | false | 0+!-0=1 |
NaN | 不变 | “NaN” | false | !NaN=true |
Infinity | 不变 | “Infinity” | true | |
-Infinity | 不变 | ”-Infinity” | true | |
1(非零) | 不变 | “1” | true | |
""(空字符串) | 0 | 不变 | false |
1+"1"="11" 10-"1"=9 // -、*、/号都是转数字。 1+ +"1"=2 1++"1"=>Uncaught ReferenceError: Invalid left-hand side expression in postfix operation |
"one"(非空、非数字) | NaN | 不变 | true |
"one"+1="one1" |
{}(任意对象) |
首先 调用 否则 调用 否则 抛出一个类型错误 |
跟转数字的规则一样 | true |
{}+[]=0 {}+1=1 ({}+1)="[object Object]1" []+{}="[object Object]" 1+{}="1[object Object]" 1-!{}=1 |
[](空数组) | 0 | ”” | true |
!+[] =true //数字0取反 ![] =false //布尔值取反 []+[]="" //字符串"" +[]=0 //数字0 +[]+[]="0" //数字0+"" []==0 =>true |
[9](包含一个数字元素) | 9 | “9” | true | [1]+1="11" |
[”a”](其他数组) | NaN | 使用.join()方法 | true |
[1,2]+"1"="1,21" //"1,2"+"1" [1,2]+1="1,21" //"1,2"+1 ![1,2]+1=1 |
function(){}(任意函数) | NaN | true |
注:1、ECMAScript 运算符优先级
运算符 | 描述 |
---|---|
. [] () | 字段访问、数组下标、函数调用以及表达式分组 |
++ — - + ~ ! delete new typeof void | 一元运算符、返回数据类型、对象创建、未定义值 |
* / % | 乘法、除法、取模 |
+ - + | 加法、减法、字符串连接 |
<< >> >>> | 移位 |
< <= > >= instanceof | 小于、小于等于、大于、大于等于、instanceof |
== != === !== | 等于、不等于、严格相等、非严格相等 |
& | 按位与 |
^ | 按位异或 |
&& | 逻辑与 |
?: | 条件 |
= oP= | 赋值、运算赋值 |
, | 多重求值 |
2、&&(逻辑与)、||(逻辑或)
&&(逻辑与)
- 如果两侧都是布尔值, 进行布尔(AND)运算。
- 否则它会先计算左侧表达式,如果为 “假值”,返回这个值,如果是“真值”,计算右侧表达式,并返回计算结果。
true && false; //false 1 && 2; //2 null && 2; //null 1-1 && 2; //0 2-1 && 0; //0
||(逻辑或)
如果两侧都是布尔值, 进行布尔(OR)运算。
否则它会先计算左侧表达式,如果为 “真值”,返回这个值,如果是“假值”,计算右侧表达式,并返回计算结果。
true || false; //true 1 || 2; //1 null || 2; //2 1-1 || 2; //2 2-1 || 0; //1
3、null与undefined区别
undefined!==null
1、定义上:null 表示一个值被定义了,定义为“空值”;undefined 表示值未定义(如变量被声明但未赋值、函数没提供制定的参数、对象没有需要的属性等等)
typeof null; // "object" typeof undefined; // "undefined"
2、类型转换上:转数字、转字符串结果不同,具体看上面隐式转换表
3、数据类型上:Undefined代表没有赋值的基本数据类型;Null代表没有赋值的引用数据类型