语言基础
一、语法
1.区分大小写
ECMAScript中一切都区分大小写。
2.标识符
所谓标识符,就是变量、函数、属性或函数参数的名称。标识符可以由一或多个下列字符组成:
- 第一个字符必须是字母、下划线(_)、或美元符号($)
- 剩下的其他字符可以是字母、下划线、美元符号或数字
3.注释
单行注释以两个斜杠字符开头(//),块状注释以一个斜杠和一个星号开头,以它们的反向组合结尾(/* */)。
4.严格模式
严格模式是一种不同的JavaScript解析和执行模型,ECMAScript3的一些不规范写法在这种模式下会被处理,对于不安全的活动将抛出错误。要对整个脚本启用严格模式,在脚本开头加上这一行:"use strict";
5.语句
ECMAScript中的语句以分号结尾。代码块由一个左花括号({)开始,一个右花括号(})标识结束。
二、关键字和保留字
ECMA-262描述了一组保留的关键字,保留的关键字不能用作标识符或属性名 。规范中也描述了一组未来的保留字,同样不能用作标识符或属性名 。
保留的关键字 | | | |
---|
abstract | enum | int | short | boolean | export | interface | static | byte | extends | long | super | char | final | native | synchronized | class | float | package | throws | const | goto | private | transient | debugger | implements | protected | volatile | double | import | public | |
三、变量
ECMAScript变量是松散类型的,意思是变量可以用于保存任何类型的数据。每个变量只不过是一个用于保存任意值的命名占位符。有三个关键词可以声明变量:var、const、let。
1.var关键字
定义变量,可以使用var操作符(一个关键词),后跟变量名(标识符),例var message;
var声明作用域 使用var操作符定义的变量会成为包含它的函数的局部变量 。
var声明提升 使用var这个关键字声明的变量会自动提升到函数作用域顶部 。
2.let声明
let声明的范围是块作用域 ,而var声明的范围是函数作用域 。 暂时性死区 let声明的变量不会再作用域中被提升 。在let声明之前的执行瞬间 被称为“暂时性死区”。 代码如下(示例):
console.log(name);
var name='Matt';
console.log(age);
let age=26;
全局声明 let在全局作业域中声明的变量不会成为window对象的属性,var则会。 代码如下(示例):
var name='Matt';
console.log(window.name);
let age=26;
console.log(window.age);
条件声明 在使用var声明变量时,由于声明会被提升,JavaScript引擎会自动将多余的声明在作用域顶部合并为一个声明。而let的作用域是块,所以不能检查前面是否已经使用let声明过同名变量,同时也就不能在没有声明的情况下声明它。 for循环中的let声明 在let出现之前,for循环定义的迭代变量会渗透到循环体外部: 代码如下(示例):
for(var i=0;i<5;i++){
}
console.log(i);
let使迭代变量的作用域仅限于for循环内部: 代码如下(示例):
for(let i=0;i<5;i++){
}
console.log(i);
3const声明
const声明变量时必须同时初始化变量 ,且尝试修改const声明的变量会导致运行时的错误 。 代码如下(示例):
const age=26;
age=36;
const name='Matt';
const name='Nicholas';
const name='Matt';
if(true){
const name='Nicholas';
}
console.log(name);
const声明的限制只适用于它指向的变量的引用 。如果const变量引用的是一个对象 ,那么会修改这个对象内部的属性并不违反const的限制 。不能用const来声明迭代变量。 代码如下(示例):
const person={};
person.name='Matt';
四、数据类型
ECMAScript有六种简单数据类型(原始类型):Undefined、Null、Boolean、Number、String和Symbol。还有一种复杂数据类型Object。
1.typeof操作符
typeof操作符确定任意变量的数据类型。 typeof操作符返回下列字符串之一:
- "undefined"表示值未定义
- "boolean"表示值为布尔值
- "string"表示值为字符串
- "number"表示值为数值
- "object"表示值为对象或null
- "function表示值为函数
- "symbol"表示值为符号
2.Undefined类型
Undefined类型只有一个值,就是特殊值undefined。当使用了var或let声明了变量但没有初始化时 ,就相当于给变量赋值了undefined值 。undefined是一个假值。 undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。 包含undefined值的变量跟未定义变量是有区别的: 代码如下(示例):
let message;
console.log(message);
console.log(age);
对于未初始化的变量和未声明变量调用typeof时,结果是"undefined" 代码如下(示例):
let message;
console.log(typeof message);
console.log(typeof age);
3.Null类型
Null类型同样是一个值,即特殊值null。逻辑上讲,null值表示一个空对象指针,给typeof传递一个null会返回"object"。 null表示"没有对象",即该处不应该有值。
4.Boolean类型
Boolean(布尔值)有两个字面值:true和false。true不等于1,false不等于0。要将一个其他类型的值转换为布尔值,可以调用特定的Boolean()转型函数。 不同类型与布尔值之间的转换规则
数据类型 | 转换为true的值 | 转换为false的值 |
---|
Boolean | true | false | String | 非空字符串 | “”(空字符串) | Number | 非零数值(包括无穷值) | 0、NaN | Object | 任意对象 | null | Undefined | N/A(不存在) | undefined |
5.Number类型
Number类型使用IEEE 754格式表示整数和浮点值。不同的数值类型相应地也有不同数值字面量格式。 最基本的数值字面量格式是十进制整数:
let intNum=55;
对于八进制字面量,第一个数字必须是0,如果字面两中包含的数字超出了应有的范围,就会忽略前缀的0,后面的数字序列会被当成十进制数。八进制字面量在严格模式下是无效的。
let octalNum1=070;
let octalNum2=079
创建十六进制字面量,必须让真正的数值前缀0x,然后是十六进制数字。
let HexNum1=0xA;
let HexNum2=0x1f
浮点值 浮点值的数值必须包含小数点,而且小数点后面必须至少有一个数字,否则数值则会变成整数。如果数值本身就是整数,只是小数点后面有0,也会转换为整数。
let floatNum1=1.1;
let floatNum2=1.;
let floatNum3=10.0
let floatNum=3.125e7;
值的范围 ECMAScript可以表示的最小数值保存在Number.MIN_VALUE中(5e-324),可以表示的最大数值保存在Number.MAX_VALUE(1.7976931348623157e+308)。用Infinity(无穷值)表示超出范围的值。 要确定一个值是不是有限大,可以使用**isFinite()**函数:
let result=Number.MAX_VALUE+Number.MIN_VALUE;
console.log(isFinite(result));
NaN NaN意思是“不是数值”(Not a Number),用来表示本来要返回数值的操作失败了(而不是抛出错误。) NaN的属性:
- 任何涉及NaN的操作始终返回NaN
- NaN不等于包括NaN在内的任何值
isNaN()函数接收一个参数,可以是任意数据类型,然后判断这个参数是否“不是数值”:
console.log(isNaN(NaN));
console.log(isNaN(10));
console.log(isNaN("10"));
console.log(isNaN("blue"));
console.log(isNaN(true));
数值转换 有三个函数可以将非数值转换为数值:Number()、parseInt()和parseFloat().Number()是转型函数,可用于任何数据类型。后两个函数主要用于将字符串转换为数值。
Number()函数的转换规则如下。
- 如果是 Boolean 值,true 和 false 将分别被转换为 1 和 0。
- 如果是数字值,只是简单的传入和返回。
- 如果是 null 值,返回 0。
- 如果是 undefined,返回 NaN。
- 如果是字符串,遵循下列规则:
- 如果字符串中只包含数字(包括前面带正号或负号的情况),则将其转换为十进制数值,即"1"会变成 1,"123"会变成 123,而"011"会变成 11(注意:前导的零被忽略了);
- 如果字符串中包含有效的浮点格式,如"1.1",则将其转换为对应的浮点数值(同样,也会忽略前导零);
- 如果字符串中包含有效的十六进制格式,例如"0xf",则将其转换为相同大小的十进制整数值;
- 如果字符串是空的(不包含任何字符),则将其转换为 0;
- 如果字符串中包含除上述格式之外的字符,则将其转换为 NaN。
- 如果是对象,则调用对象的 valueOf()方法,然后依照前面的规则转换返回的值。如果转换的结果是 NaN,则调用对象的 toString()方法,然后再次依照前面的规则转换返回的字符串值。
let num1=Number("Hello world!");
let num2=Number("");
let num3=Number("000011");
let num4=Number(true);
**parseInt()**函数专注于字符串是否包含数值模式。字符串最前面的空格会被忽略,从第一个非空格字符开始 ,如果第一个字符不是数值字符、加号或减号,parseInt()立即返回NaN。如果第一个是,则继续依次检测每个字符,直到字符串末尾,或碰到非数值字符。
var num1 = parseInt("1234blue");
var num2 = parseInt("");
var num3 = parseInt("0xA");
var num4 = parseInt(22.5);
var num5 = parseInt("070");
var num6 = parseInt("70");
var num7 = parseInt("0xf");
parseInt()也接收第二个参数,用于指定底数(进制数):
var num1 = parseInt("10", 2);
var num2 = parseInt("10", 8);
var num3 = parseInt("10", 10);
var num4 = parseInt("10", 16);
parseFloat()函数从位置0开始检测每个字符,一直解析到字符串末尾,或者解析到遇见一个无效的浮点数字字符为止。它始终都会忽略字符串开头的零 。十六进制格式的字符串则始终会被转换成0 。由于 parseFloat()只解析十进制值,因此它没有用第二个参数指定基数的用法。
var num1 = parseFloat("1234blue");
var num2 = parseFloat("0xA");
var num3 = parseFloat("22.5");
var num4 = parseFloat("22.34.5");
var num5 = parseFloat("0908.5");
var num6 = parseFloat("3.125e7");
6.String类型
String(字符串)数据类型表示零或多个16位Unicode字符序列。字符串可以使用双引号(")、单引号(’)和反引号(`)标示。 字符字面量
let text="This is the letter sigma:\u03a3.";
console.log(text.length);
字符串的特点 ECMAScript中的字符串是不可变的,意思是一旦创建,它们的值就不能变了。要修改某个变量中的字串值,必须先销毁原始的字符串,然后将包含新值的另一个字符串保存到变量中
转换为字符 toString()方法就是返回当前值的字符等价物。toString()方法可用于数值、布尔值、对象和字符串值。null和undefined值没有toString()。 多数情况下,toString()不接收任何参数。在对数值调用这个方法时,toString()可以接收一个底数参数,即以什么底数来输出数值的字符串表示。
String()始终会返回表示相应类型值的字符串。String()规则如下:
- 如果值有toString()方法,则调用该方法(不传参数)并返回结果
- 如果值是null,则返回“null”
- 如果值是undefined,返回“undefined”
模板字面量 ECMAScript6新增了使用模板字面量定义字符串的能力。与使用单引号或双引号不同,模板字面量保留换行字符,可以跨行定义字符串: 代码如下(示例):
let myMultiLineString='first line\nsecond line';
let myMultiLineTemplateLiteral=`first line
second line`;
console.log(myMultiLineString);
console.log(myMultiLineTemplateLiteral);
字符串插值 模板字面量最常用的一个特性是支持字符串差值,也就是可以在一个连续定义中插入一个或多个值。字符串插值通过在${}中使用一个JavaScript表达式实现:
let value=5;
let exponent='second';
let interpolatedTemplateLiteral=`${value} to the ${exponent} power is ${value*value}`;
console.log(interpolatedTemplateLiteral);
模板字面量标签函数 模板字面量也支持定义标签函数,而通过标签函数可以自定义插值行为。标签函数会结束被插值记号分隔后的模板和对美和表达式求值的结果。 原始字符串 模板字面量也可以直接获取原始的模板字面量内容,而不是被转换后的字符表示。可以使用默认的String.raw标签函数:
console.log('first line\nsecond line');
console.log(String.raw'first line\nsecond line');
7.Symbol类型
Symbol(符号)是ECMAScript6新增的数据类型。符号是原始值,且符号实例是唯一、不可变的。符号的用途是确保对象属性使用唯一标识符,不会发生属性冲突的危险。
符号的基本用法 符号需要使用Symbol()函数初始化。因为符号本身是原始类型 ,所以typeof操作符对符号返回symbol。调用Symbol()函数时,也可以传入一个字符串参数作为对符号的描述。Symbol()函数不能与new关键字一起作为构造函数使用。
let sym1=Symbol();
console.log(sym1);
let sym2=Symbol('foo');
comsole.log(sym2);
let sym3=Symbol('foo');
console.log(sym2==sym3);
使用全局符号注册表 如果运行时的不同部分需要共享和重用符号实例,那么可以用一个字符串作为键,在全局符号注册表中创建并重用符号。为此,需要使用Symbol.for()方法:
let sym1=Symbol.for('foo');
let sym2=Symbol.for('foo');
console.log(sym1===fym2);
Symbol.KeyFor()查询全局注册表
let s=Symbol.for('foo');
console.log(Symbol.KeyFor(s));
使用符号作为属性 Object.getOwnPropertyDescriptors()
常用内置符号 ECMAScript6也引入了一批常用内置符号,用于暴露语言内部行为,开发者可以直接访问、重写或模拟这些行为。这些内部符号都以Symbol工厂函数字符串属性的形式存在。 Symbol.asyncIterator 根据ECMAScript规范,这个符号作为一个属性表示“一个方法,该方法返回对象默认的AsyncIterator。由for-await-of语句使用。”这个符号表示实现异步迭代器API的函数。 代码如下(示例):
const myAsyncIterable=new Object();
myAsyncIterable[Symbol.asyncIterator]=async function*(){
yield "hello";
yield "async";
yield "iteration!";
};
(async ()=>{
for await(const x of myAsyncIterable){
console.log(x);
}
})();
Symbol.isConcatSpreadable 根据ECMAScript规范,这个符号作为一个属性表示“一个布尔值,如果是true,则意味着对象应该用Array.prototype.concat()打平其数组元素。” 数组对象默认情况下 被打平到已有的数组 ,false或假值 会导致整个对象被追加到数组末尾 。类数组对象默认情况下 会被追加到数组末尾 ,true或真值 会导致整个类数组对象被打平到数组实例 。 其他不是类数组对象的对象在Symbol.isConcatSpreadable被设置为true的情况下将被忽略。
代码如下(示例):
var alpha=['a','b','c'];
var numeric=[1,2,3];
var alphanumeric=alpha.concat(numeric);
console.log(alphanumeric);
代码如下(示例):
var alpha=['a','b','c'];
var numeric=[1,2,3];
numeric[Symbol.isConcatSpreadable]=false;
var alphanumeric=alpha.concat(numeric);
console.log(alphanumeric);
Symbol.iterator 根据ECMAScript规范,这个符号作为一个属性表示“一个方法,该方法返回对象默认的迭代器。由for-of语句使用”。
代码如下(示例):
var myIterable = {}
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
[...myIterable]
Symbol.match 根据ECMAScript规范,这个符号作为一个属性表示“一个正则表达式的方法,该方法用正则表达式去匹配字符串。由String.prototype.match()方法使用”。
代码如下(示例):
const regexp1 = /foo/;
regexp1[Symbol.match] = false;
console.log('/foo/'.startsWith(regexp1));
console.log('/baz/'.endsWith(regexp1));
Symbol.replace 根据ECMAScript规范,这个符号作为一个属性表示“一个正则表达式方式,该方法替换一个字符串匹配的子串。” 代码如下(示例):
class Replace1 {
constructor(value) {
this.value = value;
}
[Symbol.replace](string) {
return `s/${string}/${this.value}/g`;
}
}
console.log('foo'.replace(new Replace1('bar')));
Symbol.search 根据ECMAScript规范,这个符号作为一个属性表示“一个正则表达式方式,该方法返回一个字符串匹配正则表达式的索引。” 代码如下(示例):
class caseInsensitiveSearch {
constructor(value) {
this.value = value.toLowerCase();
}
[Symbol.search](string) {
return string.toLowerCase().indexOf(this.value);
}
}
console.log('foobar'.search(new caseInsensitiveSearch('BaR')));
Symbol.species 根据ECMAScript规范,这个符号作为一个属性表示“一个函数值,该函数作为创建派生对象的构造函数。”用Symbol.species定义静态的获取器(getter)方法,可覆盖新创建实例的原型定义。 代码如下(示例):
class MyArray extends Array {
static get [Symbol.species]() { return Array; }
}
var a = new MyArray(1,2,3);
var mapped = a.map(x => x * x);
console.log(mapped instanceof MyArray);
console.log(mapped instanceof Array);
Symbol.split 根据ECMAScript规范,这个符号作为一个属性表示“一个正则表达式方法,该方法在匹配正则表达式的索引位置拆分字符串。” 代码如下(示例):
class Split1 {
constructor(value) {
this.value = value;
}
[Symbol.split](string) {
const index = string.indexOf(this.value);
return `${this.value}${string.substr(0, index)}/${string.substr(index + this.value.length)}`;
}
}
console.log('foobar'.split(new Split1('foo')));
Symbol.toPrimitive 根据ECMAScript规范,这个符号作为一个属性表示“一个方法,该方法将对象性转换为相应的原始值。” 代码如下(示例):
const object1 = {
[Symbol.toPrimitive](hint) {
if (hint === 'number') {
return 42;
}
return null;
}
};
console.log(+object1);
Symbol.toStringTag 根据ECMAScript规范,这个符号作为一个属性表示“一个字符串,该字符串用于创建对象的默认字符串描述。” 代码如下(示例):
8.Object类型
ECMAScript中的对象Object其实就是一组数据和功能的集合。对象通过new操作符后跟对象类型的名称来创建。
let o=new Object();
每个Object实例的属性和方法:
- constructor:用于创建当前对象的函数。
- hasOwnProperty(propertyName):用于判断当前对象实例上是否存在给定的属性。
- isPrototypeOf(object):用于判断当前对象是否为另一个对象的原型。
- propertyIsEnumerable(propertyName):用于检查给定的属性是否能够使用 for-in 语句。
- toLocaleString():返回对象的字符串表示,该字符串与执行环境的地区对应。
- toString():返回对象的字符串表示。
- valueOf():返回对象的字符串、数值或布尔值表示。通常与 toString()方法的返回值相同。
五、操作符
ECMAScript描述了一组可用于操作数据值的操作符,包括数字操作符(加加、减)、位操作符、关系操作符和相等操作符等。
1.一元操作符
一元操作符只操作一个值。
递增/递减操作符 递增/递减操作符包括前缀操作符和后缀操作符。前缀操作符变量的值会在语句被求值之前改变 ,后缀操作符变量会在被求值后才发生 。 递增/递减操作符遵循规则:
- 对于字符串,如果是有效的数值形式,则转换为数值再应用改变。
- 对于字符串,如果不是有效的数值形式,则将变量的值设为NaN。
- 对于布尔值,如果是false,则转换为0在应用改变。
- 对与布尔值,如果是true,则转换为1在应用改变。
- 对于浮点值,加1或减1.
- 在应用于对象时,先调用对象的 valueOf()方法以取得一个可供操作的值。然后对该值应用前述规则。如果结果是 NaN,则在调用 toString()方法后再应用前述规则。对象变量变成数值变量。
代码如下(示例):
let s1="2";
let s2="z";
let b=false;
let f=1.1;
let o={
valueOf(){
return -1;
}
};
s1++;
s2++;
b++;
f--;
o--;
一元加和减 一元加和减操作符,一元加由一个加号(+)表示,放在变量前头,对数值没有任何影响;一元减由一个减号(-)表示,放在变量前头,主要用于把数值变为负值。
2.位操作符
按位非 按位非操作符用波浪符(~)表示,返回数值的一补数。按位非的最终结果是对数值取 反并减1 。
let num1=25;
let num2=~num1;
console.log(num2);
按位与 按位与操作符用和号(&)表示,有两个操作符。按位与操作在两个位都为1时返回1,在任何一位是0的时候返回0 。
按位或 按位或操作符用管道符(|)表示,同样有两个操作符。按位或操作在至少一位是1时返回1,两位都是0时返回0 。
按位异或 按位异或用脱字符(^)表示,同样有两个操作符。按位异或只在一位上是1的时候返回1 。
左移 左移操作符用两个小于号(<<)表示,会按照指定的位数将数值的所有位(二进制)向左移动,并保留它所操作数值的符号 。
let oldValue=2;
let newValue=oldValue<<5;
有符号右移 有符号右移由两个大于号(>>)表示,保留符号,有符号右移实际上是左移的逆运算。
let oldValue=64;
let newValue=oldValue>>5;
无符号右移 无符号右移用3个大于号表示(>>>),会将数值的所有32位都移向右边。无符号右移负数的二进制表示当成整数的二进制表示来处理。
let oldValue=-64;
let newValue=oldValue>>>5;
3.布尔操作符
布尔操作符一个有3个:逻辑非、逻辑与和逻辑或。
逻辑非 逻辑非操作符由一个叹号(!)表示。这个操作符始终返回布尔值,无论应用到的是什么数据类型。 逻辑非操作符遵循规则:
- 如果操作数是对象,则返回false。
- 如果操作数是空字符串,则返回true。
- 如果操作数是非空字符串,则返回false。
- 如果操作数是数值0,则返回true。
- 如果操作数是非0数值(包括Infinity),则返回false。
- 如果操作数是null,则返回true。
- 如果操作数是NaN,则返回true。
- 如果操作数是undefined,则返回true。
逻辑与 逻辑与操作符由两个和号(&&)表示,应用到两个值。
let result=true&&false;
逻辑与操作符遵循规则:
- 如果第一个操作数是对象,则返回第二个操作数。
- 如果第二个操作数是对象,则只有第一个操作数求值为true才会返回该对象。
- 如果两个操作数都是对象,则返回第二个操作数。
- 如果有一个操作数是null,则返回null。
- 如果有一个操作数是NaN,则返回NaN。
- 如果有一个操作数是undefined,则返回undefined。
逻辑与操作符是一种短路操作符,意思是如果第一个操作数决定了结果,那么永远不会对第二个操作数求值 。
let found=true;
let result=(found && someUnderclaredVariable);
console.log(result);
let found=false;
let result=(found && someUnderclaredVariable);
console.log(result);
逻辑或 逻辑或操作符由两个管道符(||)表示。逻辑或操作符第一个操作数求值为true,第二个操作数就不会在被求值了 。
let result=true||false;
逻辑或操作符遵循规则:
- 如果第一个操作数是对象,则返回第一个操作数。
- 如果第一个操作数求值为false,则返回第二个操作数。
- 如果两个操作数是对象,则返回第一个操作数。
- 如果两个操作数都是null,则返回null。
- 如果两个操作数都是NaN,则返回NaN。
- 如果两个操作数都是undefined,则返回undefined。
4.乘性操作符
ECMAScript定义了3个乘性操作符:乘法、除法和取模。
乘法操作符 乘法操作符由一个星号(*)表示,可用于计算两个数值的乘积。
let result=34*45;
乘法操作符遵循规则:
- 如果操作数都是数值,则执行常规的乘法运算。如果不能表示乘积,则返回Infinity或-Infinity。
- 如果有任一操作数是NaN,则返回NaN。
- 如果是Infinity乘以0,则返回NaN。
- 如果是Infinity乘以非0的有限数值,则根据第二个操作数的符号返回Infinity或-Infinity。
- 如果是Infinity乘以Infinity,则返回Infinity。
- 如果有不是数值的操作数,则先在后台用Number()将其转换为数值,然后再应用上述规则。
除法操作符 除法操作符由一个斜杠(/)表示,用于计算第一个操作数除以第二个操作数的商。
let result=66/11;
除法操作符遵循规则:
- 如果操作数都是数值,则执行常规的除法运算。如果不能表示商,则返回Infinity或-Infinity。
- 如果有任一操作数是NaN,则返回NaN。
- 如果是0除以0,则返回NaN。
- 如果是非0的有限值除以任何0,则根据第一个操作数的符号返回Infinity或-Infinity。
- 如果是Infinity除以任何数值,则根据第二个操作数的符号返回Infinity或-Infinity。
- 如果是Infinity除以Infinity,则返回NaN。
- 如果有不是数值的操作数,则先在后台用Number()将其转换为数值,然后再应用上述规则。
取模操作符 取模操作符由一个百分比符号(%)表示。
let result=26%5;
取模操作符遵循规则:
- 如果操作数是数值,则执行常规除法运算,返回余数。
- 如果被除数是无限值,除数是有限值,则返回NaN。
- 如果被除数是有限值,除数是0,则返回NaN。
- 如果是Infinity除以Infinity,则返回NaN。
- 如果被除数是有限值,除数是无限值,则返回被除数。
- 如果被除数是0,除数不是0,则返回0。
- 如果有不是数值的操作数,则先在后台用Number()将其转换为数值,然后再应用上述规则。
5.指数操作符
指数操作符**,指数赋值操作符**=。
console.log(Math.pow(3,2));
console.log(3**2);
6.加性操作符
加性操作符,即加法和减法操作符。
加法操作符 加法操作符(+)用于求两个数的和。
let result=2+5;
加法操作符遵循规则(两个数都是数值):
- 如果有一个操作数是 NaN,则结果是 NaN;
- 如果是 Infinity 加 Infinity,则结果是 Infinity;
- 如果是-Infinity 加-Infinity,则结果是-Infinity;
- 如果是 Infinity 加-Infinity,则结果是 NaN;
- 如果是+0 加+0,则结果是+0;
- 如果是-0 加-0,则结果是-0;
- 如果是+0 加-0,则结果是+0。
加法操作符遵循规则(如果有一个数值是字符串):
- 如果两个操作数都是字符串,则将第二个操作数与第一个操作数拼接起来;
- 如果只有一个操作数是字符串,则将另一个操作数转换为字符串,然后再将两个字符串拼接起来。
减法操作符 减法操作符(-)用于求两个数的差。
let result=2-1;
减法操作符遵循规则:
- 如果两个操作符都是数值,则执行常规的算术减法操作并返回结果;
- 如果有一个操作数是 NaN,则结果是 NaN;
- 如果是 Infinity 减 Infinity,则结果是 NaN;
- 如果是-Infinity 减-Infinity,则结果是 NaN;
- 如果是 Infinity 减-Infinity,则结果是 Infinity;
- 如果是-Infinity 减 Infinity,则结果是-Infinity;
- 如果是+0 减+0,则结果是+0;
- 如果是+0 减-0,则结果是-0;
- 如果是?0 减?0,则结果是+0;
- 如果有一个操作数是字符串、布尔值、null 或 undefined,则先在后台调用Number()函数将其转换为数值,然后再根据前面的规则执行减法计算。如果转换的结果是 NaN,则减法的结果就是 NaN;
- 如果有一个操作数是对象,则调用对象的 valueOf()方法以取得表示该对象的数值。如果得到的值是 NaN,则减法的结果就是 NaN。如果对象没有 valueOf()方法,则调用其 toString()方法并将得到的字符串转换为数值。
7.关系操作符
关系操作符执行比较两个值的操作,包括小于(<)、大于(>)、小于等于(<=)、大于等于(>=),都返回布尔值。
let result1=5>3;
let result2=5<3;
关系操作符遵循规则:
- 如果操作数都是数值,则执行数值比较。
- 如果操作数都是字符串,则逐个比较字符串中对于字符的编码。
- 如果有任一操作数是数值,则将另一个操作数转换为数值,在执行数值比较。
- 如果一个操作数是对象,则调用这个对象的 valueOf()方法,用得到的结果按照前面的规则执行比较。如果对象没有 valueOf()方法,则调用 toString()方法,并用得到的结果根据前面的规则执行比较。
- 如果一个操作数是布尔值,则先将其转换为数值,然后再执行比较。
8.相等操作符
相等操作符包括等于和不等于(在比较之前执行转换),全等和不全等(在比较之前不执行转换)。
等于和不等于 ECMAScript中的等于操作符用两个等于号(==)表示,如果操作数相等,则会返回true。不等于操作符用叹号和等于号(!=)表示,如果两个操作数不相等,则会返回true。两个操作符都会先进行类型转换(强制类型转换)在确定操作数是否相等 。
等于和不等于操作符遵循转换规则:
- 如果任一操作数是布尔值,则将其转换为数值再比较是否相等。
- 如果一个操作数是字符串,另一个操作数是数值,则尝试将字符串转换为数值,再比较是否相等。
- 如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法取得其原始值,再根据前面的规则进行比较。
等于和不等于操作符遵循比较规则:
- null和undefined相等。
- null和undefined不能转换为其他类型的值在进行比较。
- 如果有一个操作数是 NaN,则相等操作符返回 false,而不相等操作符返回 true。
- 如果两个操作数都是对象,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,则相等操作符返回 true;否则,返回 false。
特殊情况表
表达式 | 结果 |
---|
null==undefined | true | NaN==NaN | false | 5==NaN | false | NaN==NaN | false | NaN!=NaN | true | false==0 | true | true==1 | true | true==2 | false | undefined==0 | false | null==0 | false | “5”==5 | true |
全等和不全等 全等操作符由3个等于号(===)表示,只有在两个操作数在不转换的前提下相等才返回true。
不全等操作符用一个叹号和两个等于号(!==)
let result1=("55"==55);
let result2=("55"===55);
9.条件操作符
语法:
variable=boolean_expression ? true_value : false_value;
10.赋值操作符
简单赋值用等于号(=)表示,将右手边的值赋给左手边的变量。
let num=10;
复合赋值使用乘性、加性或位操作符后跟等于号(=)表示。
let num += 10;
11.逗号操作符
逗号操作符可以用来在一条语句中执行多个操作 ,也可以使用逗号操作符来辅助赋值 。在赋值时使用逗号操作符分隔值,最终会返回表达式中最后一个值。
let num=(3,2,4,1,5,0);
六、语句
if语句 语法:
if(condition) statement1 else statement2
代码如下(示例):
if(i>25)
console.log("Greater than 25);
else{
console.log("Less than or equal to 25);
}
do-while语句 do-while语句是一种后测试循环语句,即循环体中的代码执行后才会对退出条件进行求值 。 语法:
do{
statement
}while(expresstion);
while语句 while语句是一种先测试后循环语句,即先检测退出条件,再执行循环体内的代码。 语法:
while(expression) statement
for语句 for语句也是先测试语句,只不过增加了进入循环之前的初始化代码,以及循环执行后要执行的表达式。 语法:
for(initialization ;expression ;post-loop-expression) statement
for-in语句 for-in语句是一种严格的的迭代语句,用于枚举对象中的费符号键属性。如果for-in循环要迭代的变量是null和undefined,则不执行循环体。 语法:
for (property in expression) statement
for-of语句 for-of语句是一种严格的的迭代语句,用于遍历可迭代对象的元素。 语法:
for (property of expression) statement
标签语句 标签语句用于给语句加标签 语法:
label:statement
break和continue语句 break和continue语句为执行循环代码提供更严格的控制手段。break用于立即退出循环,强制执行循环后的下一条语句。而continue语句也用于立即退出循环,但会再次执从循环顶部开始执行。break和continue都可以与标签语句一起使用 ,返回代码中指定的位置。
with语句 with语句的用途是将代码作用域设置为特定的对象。严格模式不允许使用with,否则会抛出错误。 语法:
with (expression) statement
代码如下(示例):
let qs=location.search.substring(1);
let hostName=location.hostname;
let url=location.href;
with(location){
let qs=search.substring(1);
let hostName=hostname;
let url=href;
}
switch语句 语法:
switch (expression){
case value1:
statement
break;
case value2:
statement
break;
case value3:
statement
break;
default:
statement
}
七、函数
ECMAScript中的函数使用function关键字声明,后跟一组参数,然后是函数体。 语法:
function functionName(arg0,arg1,……,argN){
statement
}
总结
以下简要总结了 ECMAScript 中基本的要素。 ? ECMAScript 中的基本数据类型包括 Undefined、Null、Boolean、Number 和 String。 ? 与其他语言不同,ECMScript 没有为整数和浮点数值分别定义不同的数据类型,Number 类型可用于表示所有数值。 ? ECMAScript 中也有一种复杂的数据类型,即 Object 类型,该类型是这门语言中所有对象的基础类型。 ? 严格模式为这门语言中容易出错的地方施加了限制。 ? ECMAScript 提供了很多与 C 及其他类 C 语言中相同的基本操作符,包括算术操作符、布尔操作符、关系操作符、相等操作符及赋值操作符等。 ? ECMAScript 从其他语言中借鉴了很多流控制语句,例如 if 语句、for 语句和 switch 语句等。ECMAScript 中的函数与其他语言中的函数有诸多不同之处。 ? 无须指定函数的返回值,因为任何 ECMAScript 函数都可以在任何时候返回任何值。 ? 实际上,未指定返回值的函数返回的是一个特殊的 undefined 值。 ? ECMAScript 中也没有函数签名的概念,因为其函数参数是以一个包含零或多个值的数组的形式传递的。 ? 可以向 ECMAScript 函数传递任意数量的参数,并且可以通过 arguments 对象来访问这些参数。 ? 由于不存在函数签名的特性,ECMAScript 函数不能重载。
|