JavaScript是编程语言
ECAMScript是这种语言规范
在其他语言,我们学的是语言特性,而在JavaScript中,我们常学的却是模式。
一个单独的等于号(=),用于为变量赋值。
三个连续的等于号(===),用于比较两个值。
语句“做事情”。
表达式产生值。
JavaScript两种方式实现if-then-else
语句方式:
var x;
if(y >= 0){
x = y;
} else {
x = -y;
}
表达式方式:
var x = y >= 0 ? y : -y;
后面这种方式可以用于函数的参数(而前者不行)
myFunction(y >= 0 ? y:-y)
表达式语句
分号用于结束语句,而不是结束块。有一种情况会看到分号出现在块之后:函数表达式作为一个表达式时。
var x = 3 * 7;
var f = function() {};
单行注释
多行注释
x++; // single-line comment
/* this is
a multiline
comment.
*/
变量在声明后使用
var foo; // declare variable 'foo'
foo = fuck oriented object
foo是"你要让它是什么就是什么"。
变量声明和赋值可以同时进行
var foo = 6;
也可以为一个已有变量进行赋值
foo = 4; //change variable 'foo'
x += 1;
x = x + 1;
保留字(不能用于变量名、函数名、参数名)
arguments break case catch class const continue debugger default delete do else enum export extends false finally for function if implements import in instanceof interface let new null package private protected public return static super switch this throw true try typeof var void while
infinity NaN undefined
布尔值、数字、字符串、数组等。在JavaScript值所有的值都有属性。每一个属性都有一个key(或者是name)和一个value。属性就像是一条记录的字段。通过点(.)操作符可以读取属性。
value.propKey
字符串‘abc’有length这个属性
var str = 'abc';
str.length
也可以写为
'abc'.length
点操作同样可以用于给属性赋值
var obj = {}; // empty object
obj.foo = 123; // create property 'foo', set it to 123
console.log(obj.foo)
也可以通过点操作来调用方法:
'hello'.toUpperCase() // 大写
'HELLO'
原始值包括布尔值、数字、字符串、null和undefined
其他的值都是对象
这两者之前最主要的区别在于它们的比较方式;每个对象都有唯一的标识且只等于自己。
var obj1 = {};
var obj2 = {};
obj1 === obj2 // false
obj1 === obj1 //true
所有的原始值,只要编码值相同,则被认为相等
var prim1 = 123;
var prim2 = 123;
prim1 === prim2 // true
布尔值:true、false
数字:20156、1.351
字符串:‘dh’、“abc”
两个“空值”: undefined、null
特点:
(1)按值进行比较
内容比较:
3 === 3 // true
'abc' === 'abc' // true
(2)不可改变
其属性不能被改变、添加或移除:
var str = 'abc';
str.length = 1; // try to change property 'length'
str.length // => no efffect 3
str.foo = 3; // try to create property 'foo'
str.foo // => no effect, unknown property undefined
{
firstName: 'Jane',
lastName: 'Doe'
}
['apple', 'banana', 'cherry']
可以通过数字索引来访问它们
/^a+b+$/
对象具有一下特点:
(1)按引用进行比较
比较身份标识:每个值都有各自的身份标识
{} === {} // two different empty objects false
var obj1 = {};
var obj2 = obj1;
obj1 === obj2 // true
(2)默认可变
对象属性可以很自由地被改变、添加和移除
var obj1 = {}
var obj2 = 123; // add property 'foo'
console.log(obj1.foo) // 123
“空值”
var foo;
console.log(foo) // undefined
丢失的参数也会是undefined
function f(x) { return x }
console.log(f()) // undefined
访问不存在的属性,也会得到undefined
var obj = {}; // empty object
console.log(obj.foo) // undefined
检查undefined 或 null
函数允许透过undefined或null来表示缺失的值。可以通过以下显示的检查来做到同样的事情:
if(x === undefined || x === null){
...
}
也可以利用 undefined 或 null 都可被视为 false 这一事实来处理:
if(!x){
...
}
false, 0, NaN 和 ‘’ 都可被视为false
typeof用于原始值
instanceof用于对象
typeof value
typeof true // 'boolean'
typeof 'abc' // 'string'
typeof {} // empty object literal 'object'
typeof [] // empty object literal 'object'
操作数 | 结果 |
---|---|
undefined | ‘undefined’ |
null | object |
布尔值 | boolean |
数字 | number |
字符串 | string |
函数 | function |
所有其他的常规值 | object |
引擎创建的值 | JavaScript引擎可以被允许去创建一些值,且typeof的结果可以返回任意字符串(可以与列表值列出的结果都不一样) |
typeof null 返回object是一个不能修正的bug,因为这会破坏现有的代码。但这并不表示null是一个对象
value instanceof Constr
如果value是一个通过Constr构造器创建的对象,则返回true
var b = new Bar(); // object created by constructor Bar
b instanceof Bar // true
{} instanceof Object // true
[] instanceof Object // true
[] instanceof Object // Array is a subconstructor of Object true
undefined instanceof Object // false
null instanceof Object // false
以下运算会产生布尔值
以下值会被解释成false
Boolean(undefined) // false
Boolean(0) // false
Boolean(3) //true
Boolean({}) // empty object true
Boolean([]) // empty array true
二元逻辑运算符是短路的。因为如果第一个运算数就足以确定结果的话,则不会对第二个运算数做评估。
以下表达式,其中的foo()函数永远不会被调用:
false && foo()
true || foo()
二元逻辑运算符会返回运算数值得一个----可能是一个布尔值,也可能不是。
(1)与(&&)
如果第一个运算数是假值,返回它。否则,返回第二个运算数。
NaN && 'abc' // NaN
123 && 'abc' // 'abc'
(2)或(||)
如果第一个运算数是真值,返回它。否则,返回第二个运算数。
'abc' || 123 // 'abc'
'' || 123 // 123
两种类型相等
js中所有的数字都是浮点数
1 === 1.0 // true
也包含一些特殊的数字:
NaN(“not a number”) 一个错误的值
Number('xyz') // 'xyz' can't be converted to a number
NaN
Infinity多数情况下也是一个错误的值:
3/0 // Infinity
Math.pow(2, 1024) // number too large Infinity
Infinity比任何一个数都要大(NaN除外)
-Infinity比任何一个数都要小(NaN除外)
单引号 双引号之内。反斜杠(\)用于转义字符及产生一些控制字符。
'abc'
"abc"
'Did she say "Hello"?'
"Did she say \"Hello\"?"
'That\'s nice!'
"That's nice!"
'Line 1\nLine2' // newline
'Backlash: \\'
可以通过方括号来访问字符串中的单个字符:
var str = 'abc'
str[1] // 'b'
字符串的length属性可以对字符的个数进行计数:
'abc'.length // 3
像所有的原始值一样,字符串是不可变的;如果要改变一个已有的字符串,必须创建一个新的才行。
字符串可以通过加号(+)进行连接,如果其中一个运算数是字符串的话,另一个运算数将被转换为字符串:
var messageCount = 3;
console.log('You have' + messageCount + 'messages') // 'You have 3 messages'
在多个步骤转换连接字符串,可以使用+=运算符:
var str = '';
str += 'Multiple ';
str += 'pieces ';
str += 'are concatenated.';
console.log(str) // 'Multiple pieces are concatenated.'
'abc'.slice(1) // copy a substring 'bc'
'abc'.slice(1,2) // 'b'
'\t xyz '.trim() // trim whitespace 'xyz'
'mjolnr'.toUpperCase() // 'MJOLNR'
'abc'.indexOf('b') // find a string 1
'abc'.indexOf('x') // -1
str.slice(start, end) 提取字符串某个部分,start(包含),end(不包含)。
str.trim() 删除字符串的头尾空白符,空白符包括:空格、制表符tab、换行符等其他空白符等。不会更改原始字符串。
str.toUpperCase()将字符串转换为大写字母,不会更改原始字符串。
if语句有一个then从句以及一个可选的else从句
if(myvar === 0){
// then
}
if(myvar === 0){
// then
} else {
// else
}
if(myvar === 0){
// then
} else if(myvar === 1){
// else-if
} else if(myvar === 2){
// else-if
} else {
// else
}
从句仅有一个单独的语句(对 for 和 while 语句同样适用):
if(x < 0) return -x;
switch语句:
fruit的值会决定要执行哪个case:
switch(fruit){
case 'banana':
//...
break;
case 'apple':
//...
break;
default: //all other cases
//...
}
case 之后跟的“运算数”可以是任意表达式;在switch里的参数会通过===来进行比较。
for(init; condition; post_iteration){
statement
}
初始化会在循环开始前执行。
条件会在每次循环迭代之前做检查,如果是false则终止循环。
后迭代会在每次循环迭代后执行。
for(var i=0; i < arr.length; i++){
console.log(arr[i])
}
while循环语句会在条件成立的时候会持续循环
// Same as for loop above
var i = 0;
while(i < arr.length) {
console.log(arr[i])
i++;
}
do-while循环语句在条件成立时会持续循环。由于条件会跟在代码体之后,所以,这些代码体至少会执行一次:
do{
// ...
} while (condition);
有两条语句适用于所有的循环方式:
函数声明
function add(param1, param2) {
return param1 + param2;
}
函数表达式
var add = function(param1, param2){
return param1 + param2;
};
函数表达式会产生一个值,因此可以将函数作为参数直接传递给另外的函数:
someOtherFunction(function(p1, p2){ ... })
函数声明具有提升特性----它们的实体会被移动到所在作用域的开始处。这使得我们可以引用后面声明的函数。
function foo(){
bar(); //OK,bar is hoisted
function bar() {
...
}
}
var声明也具有提升的特性,但通过它们执行的赋值却不具备该特性。
function foo() {
bar(); // Not OK, bar is still undefined
var bar = function(){
// ...
};
}
函数的所有参数都可以被自由调用,会通过arguments变量来使所有参数可用。
arguments看起来像个数组,但却不具备数组的方法
function f() { return arguments }
var args = f('a', 'b', 'c');
console.log(arrs.length) // 3
console.log(args[0]) // 'a'
function f(x, y){
console.log(x, y)
return toArray(arguments);
}
// 额外的参数会被忽略
f('a', 'b', 'c') //a, b
// 丢失的参数会得到undefined这个值
f('a') // a, undefined
f() // undefined, undefined
以下是一个给参数赋上默认值的通用模式:
function pair(x, y){
x = x||0;
y = y||0;
return [x,y];
}
arguments.length
function pair(x, y){
if(arguments.length !== 2){
throw new Error('Need exactly 2 arguments');
}
...
}
arguments不是数组,它只是类似于数组。有length属性,可以通过方括号去访问它的元素。不能移除它的元素,也不能对它调用数组的方法。
function toArray(arrayLikeObject){
return Array.prototype.slice.call(arrayLikeObject)
}
function getPerson(id) {
if(id < 0){
throw new Error('ID must not be negative:'+id);
}
return {id: id} // normally: retrieved from database
}
function getPersons(ids){
var result = [];
ids.forEach(function(id){
try{
var person = getPerson(id);
result.push(person);
} catch(exception){
console.log(exception);
}
});
return result;
}
使用try语句包裹关键代码,如果try语句有异常会被抛出那么catch语句就会执行。
切换严格模式:
在JavaScript文件或者