准备以高程的章节模式,进行一下基础js的归纳与总结,大约有9章。其中有些是我自己的话,有些摘录于高程。有些则是我看了网上大佬们的总结写下来的。当然我都会标明出处。如有缺漏,欢迎指出。请多指教。
JS数据类型
ECMAScript 中有 5 种简单数据类型(也称为基本数据类型,值类型):Undefined、Null、Boolean、Number 和 String.还有 1种复杂数据类型——Object,Object 本质上是由一组无序的名值对组成的,ES6中新增复杂数据类型Symbol
1.Undefined
在使用var声明变量但未对其加以初始化时,这个变量的值就是undefined,例如
var message
messag===undefined //true
2.Null
null值代表空对象的指针,所以在typeof判断类型时会返回"object",例如
var car=null
typeof car //"object"
//在最基本的数据类型判断中typeof所判断出来的都是String类型
3.Boolean
bool类型只有true和false两种类型,存在对于其他类型值转换为bool值的判断
数据类型 | 转换为true的值 | 转换为false的值 |
---|---|---|
Boolean | true | false |
String | 任何非空字符串 | 空字符串 |
Number | 非0数字 | 0 NAN |
Object | 任何对象 | null |
Undefined | 无 | false |
4.Number
存在浮点数和整数,以及非数值(NAN),这个数值用于表示一个本来要返回数值的操作数,未返回数值的情况(这样就不会抛出错误了),针对这个值ECMAScript定义了isNaN()函数,该函数用于判断这个参数是否"不是数值"
isNaN(NAN) // true
isNaN(10) // fasle
isNaN("10") // false 字符串转换成了数字
isNaN("blue") // true
isNaN(true) // false bool类型转换成数字为1
同时有三个函数可以把非数值转换为数值 Number() ,ParseInt() ,ParseFloat()
5.String
String 类型用于表示由零或多个 16 位 Unicode 字符组成的字符序列,即字符串.存在其他类型.toString()转变为String类型,也可以String()将任何类型的值转换为字符串.
6.Object
ECMAScript 中的对象其实就是一组数据和功能的集合.对象可以通过执行 new 操作符后跟要创建的对象类型的名称来创建.
7.Symbol
为保证每个属性的名字独一无二,引入Symbol,通常可用于对象属性名的唯一确定
let s=Symbol('foo')
typeof s // "symbol"
s //Symbol(foo)
s.toString() // "Symbol(foo)"
变量-作用域-内存
1.变量类型
JS中存在两种变量类型。一种是值类型、一种是引用类型。
基本数据类型(值类型):undefined、null、Boolean、number、string、Symbol
引用类型:Object、Array、Date、RegExg、Function
在对变量进行赋值时。如果从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上,及两个变量虽然数值一样,但是都是存在栈空间上的完全独立存在。如果是引用类型的赋值 ,同样是将存储在变量对象的值复制一份放在新变量的分配空间。但实际上这个值的副本是一个指向原存储在堆空间对象的一个指针,在这里如果你对原对象的属性进行修改,所赋值的新对象的属性值依然会被覆盖。
ECMAScript中所有的函数参数都是按照值传递的,相当于开辟了一块的新的空间也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。基本类型值的传递如同基本类型变量的复制一样,而引用类型值的传递,则如同引用类型变量的复制一样,如下所示。
function addTen(num) {
num += 10;
return num;
}
var count = 20;
var result = addTen(count);
alert(count); //20,没有变化
alert(result);
在这个例子中,定义的count
为值类型,调用函数addTen
。这里传入时,先将count
的值复制给参数num
,在函数中num
就相当于函数的局部变量,因此两个变量仅仅是数值的相同,本身是完全独立的。函数内部的变量改动不会影响函数外部的变量。同理 ,如果是传入的是引用类型。复制的是指向相同对象的地址。所以,内部改变,会影响到外部变量。这里就会牵扯到一个问题,那还是按照值类型传递么?按以下代码分析
function setName(obj) {
obj.name = "Nicholas";
obj = new Object();
obj.name = "Greg";
}
var person = new Object();
setName(person);
alert(person.name); //"Nicholas"
在这个例子中创建了一个对象并将其保存在变量`person`中,然后将其复制给了参数`object`,这里两个对象引用的是同一个对象。因此 赋值了`name`之后 外部的`person`就会有了属性值。但是在函数中后面又将`obj`赋值了一个新的对象,并同样赋值了`name `属性,为什么在外部没有被修改嘞?这说明,即使在函数内部修改了参数的值,但原始的引用仍然保持未变。当在函数内部重写` obj` 时,这个变量引用的就是一个局部对象了。而这个局部对象会在函数执行完毕后立即被销毁。 **最简单的一句话讲就是引用类型的按照值传递,它这个值仅仅就是是内存地址指针,你替换的是在栈空间的一个指向对象,而不是去堆空间更改原对象**
引用https://www.jqhtml.com/45272....可进一步解释。
1.1检测类型
- typeof 主要用于判断基本值类型,null例外。但是在引用类型的判断时会判全部判断成object。
- instanceof 用于判断引用类型的值,用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性,因存在原型链的缘故。实例对象的__proto__指向了原型对象,而原型对象上的constructor属性又指回了构造函数。相当于从两边去找共同引用。如果找到,判断为true。如果是值类型则全是false
- constructor 是Object 类型的原型属性,它能够返回当前对象的构造器。但值得注意的是constructor可以被更改,所以是不安全的,undefined、null没有constructor方法。
-
Object.prototype.toString.call 因为所有引用类型的类都是集成于Object,所以你可以调用父辈的prototype上的方法,如
Object.prototype.toString() //'[Object Object]' Object.prototype.toString().call(arr) //'[Object Array]'
但是每个类都自己重写了这个方法,所以在判断的时候最后的Object会转换为自己的类型,所以调用此方法,讲call指向想要执行的对象,进行判断。但是这里如果是判断object的话,会出现上面的情况,看不出来 ,最好用instanceof
1.2 变量提升
console.log(a);
var a = 1;// 输出 undefined
===
var a
console.log(a)
a=1
-------------------------------
console.log(foo);//输出函数foo
function foo(){
}
由上可知,标识符var和函数都会存在变量提升,在ES6中,新定义了let和const两个标识符,作用在于申明块级作用域。如果类似于上面的代码,把var换成let,将输出a is not defined
。
可参考https://segmentfault.com/a/11...
2.执行环境
执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。每个执行环境都有一个与之关联的变量对象(variable object),环境中定义的所有变量和函数都保存在这个对象中。全局执行环境是最外围环境,在web浏览器中即windows对象。局部环境是每个函数自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。因此会形成一个作用域链。内部环境变量可依次向上寻找,找到最外层windows为止。
在ES6之前,JS没有块级作用域。如下面代码所示。
if (true) {
var color = "blue";
}
alert(color); //"blue"
for (var i=0; i < 10; i++){
doSomething(i);
}
alert(i); //10
第一段代码中,if声明的变量会添加到最近的环境中,即windows对象。所以外部仍能访问。第二段同理,定义的i即使是在整个for执行完后依旧是在外部的执行环境中,所以,他不能每次独立 ,而是循环的都是访问的最外环境的值。
对于标识符的查询。会沿作用域链,向上查找。如果在局部环境中找到了该标识符,搜索过程停止,变量就绪。如果在局部环境中没有找到该变量名,则继续沿作用域链向上搜索。搜索过程将一直追溯到全局环境的变量对象。如果在全局环境中也没有找到这个标识符,则意味着该变量尚未声明。
-----总结于高程P73
3.垃圾回收
待写
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。