ECMAScript学习笔记(2)--基本类型及语法相关

1、变量名区分大小写; 注意代码块的概念。
变量分为原始值和引用值:原始值存储在栈,引用值存储在堆(引用值一般是一个指针或对象名、函数名)。在C语言中编译的程序占用的内存分为以下几个部分:栈区(由系统分配/内存块连续)、堆区(由程序员分配与释放或系统结束后释放/链表结构不连续的内存块)、全局区、文字常量区、程序代码。
(1)原始类型有5种:Undefined、Null、Boolean、Number、String
Null专用值为null表示尚存在的对象,Undefined申明变量未初始化赋予该值(不等同于未定义的值,typeof无法区分是未声明还是未初始化)

成都创新互联公司于2013年成立,是专业互联网技术服务公司,拥有项目成都网站设计、成都网站制作网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元灵川做网站,已为上家服务,为灵川各地企业和个人服务,联系电话:18982081108

var oTemp;
typeof(oTemp);
console.log(oTemp == undefined);

结果为:

Hello
undefined
true

如果直接未声明使用oTemp ==undefined程序报错,null ==undefined是true说明两值相等,但是不代表含义相同。
Infinity表示无穷大,往往用isFinite()方法确保该数不是无穷大。还有一个特殊值是NaN,表示非数,不用使用NaN==NaN(输出false)判单非数,使用isNaN()判断非数。

console.log(NaN ==NaN);
var i=123;
console.log(isNaN(i)+'+++++++'+isNaN(a));

结果为:

false
false+++++++true

Number可以为32位整数也可以为64位浮点数,String大小是没有固定的

(2)引用类型通常叫做class,遇到引用值也就是处理对象。ECMAScript中其实没有类这个词,主要用对象定义,等同其他语言的类概念。

(3)以js举例:JavaScript的执行上下文生成之后,会创建一个叫做变量对象的特殊对象,基础数据类型往往都会保存在变量对象中,引用数据类型的值是保存在堆内存中的对象。JavaScript不允许直接访问堆内存数据,需要通过地址引用访问(操作地址值指向堆内存空间数据访问),如下代码:

var a = 10;
var b = a;
b = 100;
console.log(a); //a=10 a、b是两个独立的变量空间,相互不干扰

再看:

var a= { m: 10, n: 20 }
var b = a;
b. m= 15;
console.log(a.m); //输出15 a、b两个不同空间变量指向同一个地址引用

2、函数声明整体提升,变量的声明提升到(一种理解得比较形象好记忆的方式,并非本质原理,原理参考3)。
没有声明或直接赋值的变量会报错:

console.log(a) //error

后面的变量声明会提前到最前面

console.log(global); // undefined
var global = 'global';
console.log(global); // global

function fn () {
console.log(a); // undefined
var a = 'aaa';
console.log(a); // aaa
}
fn();

var声明的变量,内层变量可能会覆盖外层变量,外层变量会作用的内层;js中未经声明的变量归window所有;js中全局变量都归window所有。

var tmp = new Date();

function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world';
}
}

f(); // undefined

函数声明有两种:函数声明式、函数字面量式(因为var定义的),后者无法函数提升,如下:
console.log(f1); // function f1() {}
console.log(f2); // undefined
function f1() {}
var f2 = function() {}

3、在程序执行前的预编译中(执行上下文代码执行过程),一共有4个过程要完成:
(1)创建active object(OA)
(2)找形参和变量声明,将形参和变量声明做为OA的属性名,属性值为Undefine(此步就是变量提升的本质)
(3)将实参和形参统一
(4)在函数体中找函数声明,值赋予函数体
变量作用域要理解执行上下文的过程:创建变量对象、执行(变量赋值、函数引用、其他代码)。其中创建分三个步骤:创建arguments对象,检查function声明创建属性,检查Var变量声明创建属性。

1 var a = 10;
2 function aaa(){//step-4
3 alert(a);//step-5->执行alert,此时只能找到外面的a=10故弹框10
4 }
5 function bbb(){//step-2
6 var a = 20;
7 aaa();//step-3
8 }
9 //定义了函数没啥用,调用才是真格的所以这里是step-1
10 bbb();

作用域总结:
(1)ES6之前的js没有块级作用域(你可以自己闭包或其他方法实现),只有函数级作用域,函数外面的变量函数里面可以找到,函数里面的变量外面找不到
(2) 变量的查找是就近原则,去寻找var定义的变量,当就近没有找到的时候就去查找外层。函数声明比var声明要优先。
(3)当参数跟局部变量重名时,优先级是等同的。传参时,基本类型传值,引用类型传引用。
(4) 理解执行上下文:每个函数执行时产生执行上下文(EC),一个执行上下文定义了一个函数执行环境。

4、立即执行函数(自执行函数)的理解:
先说说如下函数的执行过程,声明函数式makeCounter(),内部定义变量i,返回一个函数体,该函数体区块变量i和被返回到的函数体makeCounter中i存储地址一致,直接上代码比较结果分析(这里有点难理解):

function makeCounter() {
// i只是makeCounter函数内的局部变量
var i = 0;

return function() {
console.log( ++i );
};
}
console.log("1----"+makeCounter().toString());
console.log("2----"+(makeCounter())());
console.log("3----"+makeCounter.toString());
console.log("4----"+parseInt(makeCounter()));
var a=makeCounter();
console.log("5----"+a);
a();
显示结果如下:
1----function () {
console.log(++i);
}
1 //注意这个结果,是由步骤2中console.log产生
2----undefined
3----function makeCounter() {
// i只是makeCounter函数内的局部变量
var i = 0;
return function () {
console.log(++i);
};
}
4----NaN
5----function () {
console.log(++i);
}
1

下面说明下为什么最后console.log的不同结果:
**每次当控制器转到可执行代码的时候,就会进入一个执行上下文。执行上下文可以理解为当前代码的执行环境,它会形成一个作用域。JavaScript中的运行环境大概包括三种情况:全局环境(JavaScript代码运行起来会首先进入该环境)、函数环境(当函数被调用执行时,会进入当前函数中执行代码)、eval。

**函数中,遇到return能直接终止可执行代码的执行,因此会直接将当前上下文弹出栈。

(1)console.log("1----"+makeCounter().toString()) 对照1,显示为function(){..},说明执行makeCounter()后函数体,return了的真正值:一个函数体
(2)console.log("2----"+(makeCounter())()) 对照显示数值1 和 2----undefined,因为函数体function(){...}后加了(),那么函数就立即执行了,所以打印了1。但是函数本身是没有返回值的,所以会显示undefine()
(3)console.log("3----"+makeCounter.toString()) 仅仅是输出了这个名为makeCounter函数体中存储的函数式全部代码内容
(4)非数返回也好理解
(5)同2理解,这里的实例化后然后用()执行和2一个道理
,唯一不同是没有console.log(a())

4、立即执行函数的写法:

// 最常用的两种写法
(function(){ / code / }()); // 推荐写法
(function(){ / code / })();
//与运算符相关联后
var i = function(){ return 10; }();
true && function(){ / code / }();
0, function(){ / code / }();

// 一元运算符
!function(){ / code / }();
~function(){ / code / }();
-function(){ / code / }();
+function(){ / code / }();

// 你也可以这样
new function(){ / code / }
new function(){ / code / }() // 带参数

6、let增加了块级的作用,不在同一块内的变量相互不干扰,外层块无法读取内层块let定义变量:

function f1() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n); // 5
}

零散的记录了一些,后面会做梳理


本文标题:ECMAScript学习笔记(2)--基本类型及语法相关
链接分享:http://scyanting.com/article/ghghsc.html