第1章 JS简介
ECMAScript 就是对实现该标准规定的各个方面内容的语言的描述:语法、类型、语句、关键字、保留字、操作符、对象
DOM 把整个页面映射为一个多层节点结构。HTML或 XML 页面中的每个组成部分都是某种类型的节点,这些节点又包含着不同类型的数据。通过 DOM 创建的表示文档的树形图,开发人员获得了控制页面内容和结构的主动权。借助DOM 提供的 API,开发人员可以轻松自如地删除、添加、替换或修改任何节点。
从根本上讲,BOM 只处理浏览器窗口和框架;但人们习惯上也把所有针对浏览器的 JavaScript 扩展算作 BOM 的一部分。下面就是一些这样的扩展:
弹出新浏览器窗口的功能;
移动、缩放和关闭浏览器窗口的功能;
提供浏览器详细信息的 navigator 对象;
提供浏览器所加载页面的详细信息的 location 对象;
提供用户显示器分辨率详细信息的 screen 对象;
对 cookies 的支持;
像 XMLHttpRequest 和 IE 的 ActiveXObject 这样的自定义对象。
JavaScript 是一种专为与网页交互而设计的脚本语言,由下列三个不同的部分组成:
ECMAScript,由 ECMA-262 定义,提供核心语言功能;
文档对象模型(DOM),提供访问和操作网页内容的方法和接口;
浏览器对象模型(BOM),提供与浏览器交互的方法和接口。
JavaScript 的这三个组成部分,在当前五个主要浏览器(IE、Firefox、Chrome、Safari 和 Opera)中都得到了不同程度的支持。
第3章 基本概念
3.4 数据类型
标识符,就是指变量、函数、属性的名字,或者函数的参数
/*
* 这是一个多行
* (块级)注释
*/
上面注释中的第二和第三行都以一个星号开头,但这不是必需的。之所以添加那两个星号,纯粹是为了提高注释的可读性(这种格式在企业级应用中用得比较多)。
ECMAScript 的变量是松散类型的,所谓松散类型就是可以用来保存任何类型的数据。
ECMAScript 中有 5 种简单数据类型(也称为基本数据类型):Undefined、Null、Boolean、Number
和 String。还有 1种复杂数据类型——Object
实际上,undefined 值是派生自 null 值的,因此 ECMA-262 规定对它们的相等性测试要返回 true:
alert(null == undefined); //true
浮点数值,就是该数值中必须包含一个小数点,并且小数点后面必须至少有一位数字。
NaN 与任何值都不相等,包括 NaN 本身: alert(NaN == NaN); //false
有 3 个函数可以把非数值转换为数值:Number()、parseInt()和 parseFloat()。第一个函数,即转型函数 Number()可以用于任何数据类型,而另两个函数则专门用于把字符串转换成数值。
var num1 = parseInt("10", 2); //2 (按二进制解析) 将数值10由二进制转化为十进制
var num4 = parseInt(22.5); // 22
var num3 = parseFloat("22.5"); //22.5
转化为字符串:toString()方法
var age = 11;
var ageAsString = age.toString(); // 字符串"11"
在调用数值的 toString()方法时,可以传递一个参数:输出数值的基数。默认情况下,toString()方法以十进制格式返回数值的字符串表示。而通过传递基数,toString()可以输出以二进制、八进制、十六进制:
var num = 10;
alert(num.toString()); // "10"
alert(num.toString(2)); // "1010" 将数值10由十进制转化为二进制
转型函数String():在不知道要转换的值是不是 null 或 undefined 的情况下,还可以使用转型函数 String(),这个函数能够将任何类型的值转换为字符串。
var value1 = 10;
var value2 = true;
var value3 = null;
var value4;
alert(String(value1)); // "10" 如果值有 toString()方法,则调用该方法(没有参数)并返回相应的结果
alert(String(value2)); // "true"
alert(String(value3)); // "null" 因为 null 和 undefined 没有 toString()方法
alert(String(value4)); // "undefined"
3.5 操作符
ECMA-262 描述了一组用于操作数据值的操作符,包括算术操作符(如加号和减号)、位操作符、关系操作符和相等操作符。ECMAScript 操作符能够适用于很多值,例如字符串、数字值、布尔值,甚至对象。不过,在应用于对象时,相应的操作符通常都会调用对象的valueOf()和(或)toString()方法,以便取得可以操作的值。
递增和递减操作符直接借鉴自 C,而且各有两个版本:前置型和后置型。执行前置递增和递减操作时,变量的值都是在语句被求值以前改变的。
var age = 29;
var anotherAge = --age + 2;
alert(age); // 输出 28
alert(anotherAge); // 输出 30
var num1 = 2;
var num2 = 20;
var num3 = num1-- + num2; // 等于 22 后置递增和递减操作是在包含它们的语句被求值之后才执行的
var num4 = num1 + num2; // 等于 21
var b = false; b++; // 值变成数值 1 ;因为在应用于布尔值 false 时,先将其转换为 0 再执行加减 1 的操作。
---插入书签 to be continued
3.6 语句
CMA-262 规定了一组语句(也称为流控制语句)。
代码块:以一对花括号括起来的多行代码
var count = 10;
for (var i = 0; i < count; i++){
alert(i); } //最后弹出9
由于 ECMAScript 中不存在块级作用域,因此在循环内部定义的变量也可以在外部访问到:
var count = 10;
for (var i = 0; i < count; i++){
alert(i); }
alert(i); //最后弹出10
不要用for in遍历数组,全部统一采用标准的for循环变量数组( 我们无法保证我们引入的js是否会采用prototype扩展原生的Array )
遍历对象,由于for没办法提供理想的遍历,这里建议使用for in,因为for in能获取索引和属性值。但存在浏览器兼容问题。
for (i=0;i<10;i++)
if (i==6) continue;/*如果i==6则不再执行下面的if语句,而是直接进行下一轮循环*/
if (i==7) break;/*如果i==7,则不再执行剩余的循环(i==7也不执行),直接退出for循环去执行下面的*/
3.7 函数
ECMAScript 中的参数在内部是用一个数组来表示的。函数接收到的始终都是这个数组,而不关心数组中包含哪些参数
function sayHi(name, message) {
alert("Hello " + name + "," + message);
}
这个函数可以通过其函数名来调用,后面还要加上一对圆括号和参数(圆括号中的参数如果有多个,
可以用逗号隔开)。sayHi("Nicholas", "how are you today?");
除了 return 语句之外,没有任何声明表示该函数会返回一个值。
第4章 变量、作用域和内存问题
ECMAScript 变量可能包含两种不同数据类型的值:基本类型值和引用类型值。基本类型就是保存在栈内存中的简单数据段,而引用类型指的是那些保存在堆内存中的对象。在将一个值赋给变量时,解析器必须确定这个值是基本类型值还是引用类型值。第 3 章讨论了 5 种基本数据类型:Undefined、Null、Boolean、Number 和 String。这 5 种基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值。引用类型的值是保存在内存中的对象。
访问变量有按值和按引用两种方式,而参数只能按值传递。
所有全局变量和函数都是作为 window 对象的属性和方法创建的。每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。当代码在一个环境中执行时,会创建变量对象的一个作用域链(scope chain)。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。
在 JavaScript 中,if 语句中的变量声明会将变量添加到当前的执行环境(在这里是全局环境)中。在使用 for 语句时尤其要牢记这一异,例如:
for (var i=0; i < 10; i++){
doSomething(i);
}
alert(i); //10
对于 JavaScript 来说,由 for 语句创建的变量 i 即使在 for 循环执行结束后,也依旧会存在于循环外部的执行环境中。
搜索标识符:先在局部环境中搜索,如果局部环境中搜索不到,再到全局环境中搜索
JavaScript 具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存。这种垃圾收集机制的原理其实很简单:找出那些不再继续使用的变量,然后释放其占用的内存。为此,垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间),周期性地执行这一操作。
将变量设置为 null 意味着切断变量与它此前引用的值之间的连接。当垃圾收集器下次运行时,就会删除这些值并回收它们占用的内存。
栈内存和堆内存: 基本类型值在内存中占据固定大小的空间因此被保存在栈内
一般来说栈内存线性有序存储,容量小,系统分配效率高。而堆内存首先要在堆内存新分配存储区域,之后又要把指针存储到栈内存中,效率相对就要低一些了。
垃圾回收方面,栈内存变量基本上用完就回收了,而推内存中的变量因为存在很多不确定的引用,只有当所有调用的变量全部销毁之后才能回收。
引用类型,值大小不固定,栈内存中存放地址指向堆内存中的对象,是按引用访问的。栈内存中存放的只是该对象的访问地址,在堆内存中为这个值分配空间。由于这种值的大小不固定,因此不能把它们保存到栈内存中。但内存地址大小的固定的,因此可以将内存地址保存在栈内存中。 这样,当查询引用类型的变量时, 先从栈中读取内存地址, 然后再通过地址找到堆中的值。对于这种,我们把它叫做按引用访问。当我们看到一个变量类型是已知的,就分配在栈里面,比如INT,Double等。其他未知的类型,比如自定义的类型,因为系统不知道需要多大,所以程序自己申请,这样就分配在堆里面。基本类型大小固定,引用类型大小不固定,分开存放使得程序运行占用内存最小。