1、xmind图
2、基本数据类型和引用数据类型
基本类型值是指简单的数据段,而引用类型指由多个值构成的对象,他们有如下三点区别
- 基本类型按值访问,所以我们可以直接操作保存在变量中的实际的值,而引用类型保存的是对象的内存地址,我们不能直接操作地址,所以我们操作的是对象的引用
- 引用类型的值可以添加属性和方法,而基本数据如果添加方法会报错
- 复制变量时的区别,基本类型是把这个值复制到新变量分配的位置上,他们是独立的互不影响的个体,而引用类型是将指针复制给了新变量,而这个指针指向的是同一个内存地址,所以这两个变量将引用同一个对象,一个变量变化时,会影响到另一个变量。
tips:传递参数:
js中访问变量有按值和按引用两种方式,但函数的传递参数都是按值传递的,为了证明参数是按值传递的,请看下面的例子
function setName(obj){
obj.name = 'anne';
obj = new Object();
obj.name = 'ly';
}
var person = {};
setName(person);
console.log(person.name); //anne
将person作为参数传入时,传入的是person对象的内存地址,所以给obj添加属性时,也会修改person的值,但给obj重新赋值时,就改变了obj指向的内存地址,此时obj跟person就无关了,所以再修改obj的name时,不会再修改person的值,如果是按对象的引用传值,person会跟着obj一起变化
3、Number类型
- 浮点数的计算:
由于计算机能表示的数字是有限的,而浮点数是无限的,所以很多小数都是以非常近似的值保存,这就是为什么浮点数的计算会产生误差的原因,比如0.2+0.1是不等于0.3,它可能等于0.3000000004,等等其他近视值。
- NaN(Not a Number):
是一个特殊的值,这个值用于表示一个本来要返回数值的操作数未返回数值的情况,任何数值除以非数值都会返回NaN,任何涉及NaN的操作都返回NaN,NaN不等于任何值,包括它自身。
- isNaN():
isNaN函数可以一个变量是否不是数值或者是否不能转换为数值,如果不是数值返回true,如果是数值返回false
isNaN(NaN); //true
isNaN(10); //false
isNaN("10"); //false,可以转换为数值
isNaN('blue'); //true,不能转换为数值
isNaN(true); //false,能转化为1
- 数值转化:
parseInt()、parseFloat():他们可以接收第二个可选参数,表示第一个参数要按多少进制来进行转化,默认为10进制
可以通过typeof检测变量的类型,它返回这个类型的字符串形式。
4、String类型
字符串一旦创建,它们的值就不能改变,要改变某个变量保存的字符串,首先要销毁原来的字符串,然后再用另一个包含新值的字符串填充该变量,这就是为什么在老版本的浏览器中拼接字符串慢的原因
5、Object类型
Object的实例都具有以下属性和方法:
- constructor:指向构造函数,constructor是原型链上的方法,在后面介绍面向对象编程的时候会具体讲解
- hasOwnProperty(propertyName):检测给定的属性是否是在对象实例中,而不是在原型链中
- isPrototypeof(object):用于检测传入的对象是否是当前对象的原型
- toString():返回对象的字符串表示
- valueof():返回对象的字符串、数值或布尔表示,通常与toString返回相同
TIPS:Object是个基础类型,其他所有类都继承成Object,所以所有对象都会有这些属性和方法。
6、Function类型
- 函数的两种定义方式:函数声明和函数表达式。
//函数声明
function test(){
console.log('test');
}
//函数表达式
var test = function(){
console.log('test')
}
解析器在执行环境中加载数据时,解析器会率先读取函数声明,并使其在执行任何代码之前可用,而函数表达式,则必须等到解析器执行到它所在的代码行,才会真正的被解释执行。简言之,就是可以在函数声明之前调用函数,而在函数表达式之前调用函数会报错(函数表达式类似于变量赋值,存在声明提升,因此在函数表达式之前它的值为undefined,调用undefined当然会报错)。
- 函数内部属性:this和arguments
this引用的是函数执行时的环境对象
var color = 'red';
var obj = {
color:'blue'
}
function sayColor(){
console.log(this.color);
}
sayColor(); //red
o.sayColor = sayColor;
o.sayColor(); //blue
arguments是一个类数组对象,包含所有传入函数的参数,另外它还有一个callee的属性,该属性是一个指针,指向拥有arguments对象的函数,这在递归时比较有用,在改变函数名时不需要改变再改变函数内部的调用。
function factorial(num){
if(num<=1){
return 1;
}else{
return num*arguments.callee(num-1); //arguments.callee就是factorial函数
}
}
- 函数的方法:call()、apply()、bind():它门可以变化函数体内this的指向。
call():第一个参数是在其中运行函数的作用域,即this值的指向,之后的所有参数是传递给函数的参数。
apply():第一个参数是在其中运行函数的作用域,即this值的指向,第二个参数是传递给函数的参数数值
它门两个之间除了使用方式不同,没有其他的不同。
var obj1 = {
color:'blue'
}
var obj2 = {
color:'red'
}
function sayColor(c1,c2){
console.log(this.color,c1,c2);
}
sayColor.call(obj1,'grey','orange'); //blue,grey,orange
sayColor.apply(obj2,['black','white']); //red,black,white
ES5引入了bind(),这个方法会创建一个新函数,其this值会被绑定到传给bind()函数的值
var obj = {
color:'blue'
}
function sayColor(c1,c2){
console.log(this.color,c1,c2);
}
var otherSayColor = sayColor.bind(obj,'grey','green');
otherSayColor() //blue grey green
7、基本包装类型
除了undefine和null基本类型之外,其他三种基本类型依然可以像对象一样调用方法,如toString()等等,为什么呢?因为为了便于操作基本数据类型,js提供了三个特殊的引用类型:Boolean、Number、String。
每当读取一个基本类型值的时候,后台就会创建一个与之对应的基本包装类型的对象,从而让我们能够调用一些方法来操作这些数据。来看下面的例子:
var s1 = 'some text';
var s2 = s1.substring(2);
基本类型值不是对象,从逻辑上说它们不应该有方法,但其实为了我们能更好的操作这些数据,后台已经自动完成了一系列的处理,当第二行代码访问到s1时,访问过程处于一种读取模式,在读取模式中访问字符串时,后台完成了以下处理:
1、自动创建String对象的一个实例
2、在实例上调用指定的方法
3、销毁这个实例
自动创建的基本包装类型的对象只存在于一行代码执行的瞬间,执行完成后就已经销毁了这个实例,所以我们在给基本类型添加方法和属性的时候会报错。
var s1 = 'some text';
var s2 = s1.substring(2);
s1.color = 'red';
console.log(s1.color); //undefine,在执行完第二句代码时,创建的基本包装类型对象已经被销毁了,
//当执行到第三句的时候,读取s1,又创建了新的对象,当执行到第四句时,也会读取s1,
//又创建新的对象,所以color为undefine