ECMAScript的变量是松散类型,也就是说可以用来保存任何类型的数据。每个变量仅仅是一个用于保存值的占位符。
我们通过var操作符来声明一个变量:var message;
var message = "hi";
message = 100; // 有效,但不推荐
我们不建议修改变量保存值的类型。
JavaScript中用var申明的变量是有作用域的。
1. 如果变量在函数内部申明,则该变量的作用域为整个函数体,在函数外不可引用(会报ReferenceError)
2. 由于函数可以嵌套,内部函数可以访问外部函数定义的变量,反过来不可以。
变量提升:JS函数定义会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部
'use strict';
function foo() {
var x = 'Hello, ' + y;//这里不会报错,因为y在后面有申明。但是此时y为undefined。
alert(x);
var y = 'Bob';
}
foo();
我们要严格遵守:在函数内部首先申明所有变量。
常见的做法是用一个var申明函数内的所有变量,用逗号隔开:
function foo() {
var
x = 1, // x初始化为1
y = x + 1, // y初始化为2
z, i; // z和i为undefined
// 其他语句:
for (i=0; i<100; i++) {
...
}
}
不在任何函数内定义的变量就具有全局作用域。而window是JavaScript的一个全局对象(Node里面没有window全局对象)。而全局作用域的变量实际上是被绑定在window的一个属性。而 函数对于JavaScript来说也是一个对象,所以我们也可以通过window来访问。
由此,可以推断出来,常用的alert()函数也是window对象的一个属性。(所以我们可以对alert函数重构,但是最好不要这么做)。
—->说明JS只有一个全局作用域。
问题:因为全局变量都会绑定到window上面。而不同的JavaScript文件如果使用了相同的全局变量,或者定义了相同名字的顶层函数,都可能会造成命名冲突,而且很难察觉。
解决办法:我们可以把自己的所有变量和函数全部绑定到一个全局变量当中。
// 唯一的全局变量MYAPP:
var MYAPP = {};
// 其他变量:
MYAPP.name = 'myapp';
MYAPP.version = 1.0;
// 其他函数:
MYAPP.foo = function () {
return 'foo';
};
而MYAPP就是一个名字空间,可以大大减少全局变量的冲突。(比如JQuery,underscore)
需要注意的是,for循环等语句是无法定义具有局部作用域的变量的(也就是说没有块级作用域)。
function foo() {
for (var i=0; i<100; i++) {
//
}
i += 100; // 仍然可以引用变量i
}
所以,ES6引入了新的关键字let,用来解决块级作用域的问题。
'use strict';
function foo() {
var sum = 0;
for (let i=0; i<100; i++) {
sum += i;
}
i += 1; // SyntaxError
}
问题:ES6之前,没有专门的常量。只是通过全部大写来习惯性规定为是常量(但还是变量)。
所以ES6引入了新的关键字const来定义常量,const和let都具有块级作用域。
const PI = 3.14;
ECMAScript中的变量包含两种不同数据类型值:基本类型值和引用类型值。
基本类型值指的是简短的数据段。有Undefined、 Null、 Boolean、 Number 和 String这5种基本数据类型。
Undefined类型只有一个值,即特殊的undefined。
我们使用var声明变量但还没有初始化,这个变量的值就是undefined。(引入undefined的目的是为了正式区分空对象指针和未经初始化的变量)
var message; // 这个变量声明之后默认取得了 undefined 值
// 下面这个变量并没有声明
// var age
alert(message); // "undefined"
alert(age); // 产生错误
然而我们对为初始化的变量和未声明的变量使用typeof操作符,都返回undefined。(奇怪,但是有其逻辑上的合理性)
Null类型只有一个值,即null。null值逻辑上表示空对象指针。所以typeof返回“object”。
如果我们定义的变量准备将来用于保存对象,我们最好将变量显式初始化为null。(可以进一步区分null和undefined)
JS不区分整数和浮点数(双精度型),同一使用number表示。
比如:
123; // 整数123
0.456; // 浮点数0.456
1.2345e3; // 科学计数法表示1.2345x1000,等同于1234.5
-99; // 负数
NaN; // NaN表示Not a Number,当无法计算结果时用NaN表示
Infinity; // Infinity表示无限大,当数值超过了JavaScript的Number所能表示的最大值时,就表示为Infinity
对于NaN和infinity的区别,Infinity表示无穷大,比如 1/0 就是 Infinity;而 0/0就是NaN。
NaN(not a number),是一个特殊的number类型。用于表示一个本来要返回数值的操作数未返回数值的情况(这样就不会抛出错误了)。
NaN与任何值都不相等,任何涉及NaN的操作都会返回NaN。
isNaN( )函数用于判断是否是NaN.比如“”就不是(因为其可以转为0),而“a”就是(无法转为number)。
JS字符串使用‘ ’或“ ”表示,如果字符串包含 ’,可以在外面使用 ”包括,如果字符串包含 ”和 ’,可以使用 \ 转义,比如\n,\t等,
\u4e2d\u6587 表示中文
ES6新增加了一种表示多行字符串的方式(是反引号),直接使用:
`这是
多行
字符串
`;
模板字符串
多个字符串相联可以使用+号,自动转换成字符串。
而ES6新增加了一种模板字符串,可以自动替换字符串中的变量,也是使用反引号。
常见的操作字符串
假定 var s="abc"
s.length
返回字符串长度
字符串可以使用下标操作,但是溢出的时候不报错,但一律返回undefined。
强调的是,字符串是不可变的,如果对字符串某个索引赋值,不会报错,但是没有效果
toUpperCase() toLowerCase() 返回新的字符串,原字符串没有修改
indexOf() 检索,检索失败返回-1
substring()返回指定区间的子串
引用类型值是保存在内存中的对象。变量赋值对象的时候,其实里面是对象的指针(我的理解)。所以基本类型值的赋值直接是新的值,对新的值修改不会改变原来的值:
而对引用类型变量的复制其实只是引用的复制。
另外,函数的参数传递仍然是值传递。
通常有两种方式来创建Object类型的实例:
在ECMAScript中,所有的对象都是Object类型(这是重要的思想)。
每个Object的实例都有下面的属性和方法:
ECMA-262中的对象行为不一定适用于JS中的其他对象。比如浏览器环境中的对象。BOM和DOM都属于宿主对象。
我们通过new和对象字面量{}创建新的对象的区别在于,{}不会调用构造函数
JS的对象是无序的集合数据类型,我们可以通过 . 操作符 或者下标来访问对象的属性。
如果对象的属性必须是有效的变量名。如果属性名包含特殊字符,需要用‘ ’包括起来(并且不能直接通过 . 操作符访问)。如果访问不存在的属性不会报错,,直接返回undefined。
JS的对象是动态类型,可以自由地给其添加或删除属性(通过delete)。
JS中的Array类型可以包含任意数据类型,通过索引下标来访问。
注意:
数组的常用方法
Array.indexOf( ) : 搜索指定元素的位置
Array.slice():切片操作,返回新的Array,可以通过不传递参数复制一个新的数组(返回的是新的数组)
push和pop:在末尾添加若干元素;删除末尾的一个元素
unshift和shift:在开头添加若干元素;删除开头的一个元素(push,pop,unshift和shift都是在原数组上操作)
sort( ):按照默认顺序排序
reverse(): 转置数组 (值的注意的是sort和reverse是在原数组上操作)
splice():可以从指定的索引开始删除若干元素,再从该位置添加若干元素
concat():用于连接另一个数组,返回新的数组(concat可以接受任意个元素和Array,函数会自动拆分)
join(): join方法非常实用,可以将数组的每个元素通过指定的操作符连接成字符串
Date在JS中表示日期和时间,获取系统当前时间,我们可以new一个Date。
var now = new Date();
now; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
now.getFullYear(); // 2015, 年份
now.getMonth(); // 5, 月份,注意月份范围是0~11,5表示六月
now.getDate(); // 24, 表示24号
now.getDay(); // 3, 表示星期三
now.getHours(); // 19, 24小时制
now.getMinutes(); // 49, 分钟
now.getSeconds(); // 22, 秒
now.getMilliseconds(); // 875, 毫秒数
now.getTime(); // 1435146562875, 以number形式表示的时间戳
时间戳是没有时区差别的。并且JS中用0-11表示月份。
Date常用的函数
ECMAScript是通过RegExp类型来支持正则表达式的,语法类似Perl
var expression = /pattern / flags;
具体的可以看google。
JavaScript中函数是计算机科学中的first-class function概念,它本身也是一个对象。每个函数都是Function类型的实例(和其他引用类型一样具有属性和方法)。
JavaScript中是没有重载的,如果声明了两个同名函数,后面的会覆盖掉前面的同名函数。
为了便于操作基本类型值, ECMAScript 还提供了 3 个特殊的引用类型: Boolean、 Number 和String。这些类型与前面介绍的其他引用类型相似,但同时也具有与各自的基本类型相应的特殊行为。
本文原创发表于CSDN,为BruceYuj最近所学总结,欢迎转载,但请注明出处