JS语法总结(一)
JavaScript 是一个脚本语言。
它是一个轻量级,但功能强大的编程语言
1.JS变量
1.1 什么是变量
变量是用于存储信息的"容器"。
例如:
var x=5;
var y=6;
var z=x+y;
在代数中,我们使用字母(比如 x)来保存值(比如 5)。
通过上面的表达式 z=x+y,我们能够计算出 z 的值为 11。
在 JavaScript 中,这些字母被称为变量。
与代数一样,JavaScript 变量可用于存放值(比如 x=5)和表达式(比如 z=x+y)。
1.2 变量命名
变量可以使用短名称(比如 x 和 y),也可以使用描述性更好的名称(比如 age, sum, totalvolume)。
变量必须以字母开头
变量也能以 $ 和 _ 符号开头(不过我们不推荐这么做)
变量名称对大小写敏感(y 和 Y 是不同的变量)
1.3 声明变量(以var为例)
在 JavaScript 中创建变量通常称为"声明"变量。
我们使用 var 关键词来声明变量:
var carname;
变量声明之后,该变量是空的(它没有值)。
如需向变量赋值,请使用等号:
carname="Volvo";
也可以在声明变量时对其赋值:
var carname="Volvo";
1.4 js-变量定义关键字const,var,let
1.4.1var定义的变量可以修改,如果不初始化会输出undefined,不会报错。
var a = 1;
// var a;//不会报错
console.log('函数外var定义a:' + a);//可以输出a=1
function change(){
a = 4;
console.log('函数内var定义a:' + a);//可以输出a=4
}
change();
console.log('函数调用后var定义a为函数内部修改值:' + a);//可以输出a=4
1.4.2const定义的变量不可以修改,而且必须初始化。
const b = 2;//正确
// const b;错误,必须初始化
console.log('函数外const定义b:' + b);//有输出值
// b = 5;
// console.log('函数外修改const定义b:' + b);无法输出
1.4.3let是块级作用域,函数内部使用let定义后,对函数外部无影响。
let c = 3;
console.log('函数外let定义c:' + c);//输出c=3
function change(){
let c = 6;
console.log('函数内let定义c:' + c);//输出c=6
}
change();
console.log('函数调用后let定义c不受函数内部定义影响:' + c);//输出c=3
1.5 var和let的区别:
1.5.1作用域
通过var定义的变量,作用域是整个封闭函数,是全域的 。通过let定义的变量,作用域是在块级或是子块中。
for (let i = 0; i < 10; i++) {
// ...
}
console.log(i);
// ReferenceError: i is not defined
//计数器i只在for循环体内有效,在循环体外引用就会报错
1.5.2变量提升现象
不论var声明的变量处于当前作用域的第几行,都会提升到作用域的头部。 var 声明的变量会被提升到作用域的顶部并初始化为undefined,而let声明的变量在作用域的顶部未被初始化。
var 的情况
console.log(foo); // 输出undefined
var foo = 2;
相当于
var foo; //声明且初始化为undefined
console.log(foo);
foo=2;
let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;
//相当于在第一行先声明bar但没有初始化,直到赋值时才初始化
但是直接用let声明变量不赋值是会打印undefined,还是初始化了
let a;
alert(a);//值为undefined
alert b;//会报错
let b;
1.5.3块级作用域
只要块级作用域内存在let命令,它所声明的变量就“绑定”这个区域,不再受外部的影响。而且,在代码块内,使用let命令声明变量之前,该变量都是不可用的,尽管代码块外也存在相同全局变量。
示例一:
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
示例二:
var tmp = 123;
if (true) {
//tmp = 'abc';
let tmp;
}
alert(tmp); //输出值为123,全局tmp
//与局部tmp不影响(假设前面没有非法使用、没有抛错的情况下)
1.5.4 let不允许在相同作用域内,重复声明同一个变量。
// 报错
function () {
let a = 10;
var a = 1;
}
// 报错
function () {
let a = 10;
let a = 1;
}
2.JS数据类型
————————————————————————————
字符串(String)、数字(Number)、布尔(Boolean)、数组(Array)、对象(Object)、空(Null)、未定义(Undefined)。
————————————————————————————
2.1JS字符串
字符串可以是引号中的任意文本。可以使用单引号或双引号:
var carname="Volvo XC60";
var carname='Volvo XC60';
也可以在字符串中使用引号,只要不匹配包围字符串的引号即可:
var answer="It's alright";
var answer="He is called 'Johnny'";
var answer='He is called "Johnny"';
2.2数字(Number)
JavaScript 只有一种数字类型。数字可以带小数点,也可以不带:
var x1=34.00; // 使用小数点来写
var x2=34; // 不使用小数点来写
极大或极小的数字可以通过科学(指数)计数法来书写:
var y=123e5; // 12300000
var z=123e-5; // 0.00123
数字方法
2.2.1toString() 方法
toString() 以字符串返回数值。
所有数字方法可用于任意类型的数字(字面量、变量或表达式):
var x = 123;
x.toString(); // 从变量 x 返回 123
(123).toString(); // 从文本 123 返回 123
(100 + 23).toString(); // 从表达式 100 + 23 返回 123
2.2.2toExponential() 方法
toExponential() 返回字符串值,它包含已被四舍五入并使用指数计数法的数字。
参数定义小数点后的字符数:
var x = 9.656;
x.toExponential(2); // 返回 9.66e+0
x.toExponential(4); // 返回 9.6560e+0
x.toExponential(6); // 返回 9.656000e+0
2.2.3toFixed() 方法
toFixed() 返回字符串值,它包含了指定位数小数的数字:
var x = 9.656;
x.toFixed(0); // 返回 10
x.toFixed(2); // 返回 9.66
x.toFixed(4); // 返回 9.6560
x.toFixed(6); // 返回 9.656000
2.2.4toPrecision() 方法
toPrecision() 返回字符串值,它包含了指定长度的数字:
var x = 9.656;
x.toPrecision(); // 返回 9.656
x.toPrecision(2); // 返回 9.7
x.toPrecision(4); // 返回 9.656
x.toPrecision(6); // 返回 9.65600
2.2.5valueOf() 方法
valueOf() 以数值返回数值:
var x = 123;
x.valueOf(); // 从变量 x 返回 123
(123).valueOf(); // 从文本 123 返回 123
(100 + 23).valueOf(); // 从表达式 100 + 23 返回 123
2.2.6Number() 方法
Number() 可用于把 JavaScript 变量转换为数值:
x = true;
Number(x); // 返回 1
x = false;
Number(x); // 返回 0
x = new Date();
Number(x); // 返回 1404568027739
x = "10"
Number(x); // 返回 10
x = "10 20"
Number(x); // 返回 NaN
2.2.7parseInt() 方法
parseInt() 解析一段字符串并返回数值。允许空格。只返回首个数字:
parseInt("10"); // 返回 10
parseInt("10.33"); // 返回 10
parseInt("10 20 30"); // 返回 10
parseInt("10 years"); // 返回 10
parseInt("years 10"); // 返回 NaN
2.3布尔(Boolean)
布尔(逻辑)只能有两个值:true 或 false。
var x=true;
var y=false;
2.4数组(Array)
下面的代码创建名为 cars 的数组:
var cars=new Array();
cars[0]="Saab";
cars[1]="Volvo";
cars[2]="BMW";
var cars=new Array("Saab","Volvo","BMW");
var cars=["Saab","Volvo","BMW"];
数组下标是基于零的,所以第一个项目是 [0],第二个是 [1],以此类推。
2.5对象(Object)
对象由花括号分隔。在括号内部,对象的属性以名称和值对的形式 (name : value) 来定义。属性由逗号分隔:
var person={firstname:"John", lastname:"Doe", id:5566};
上面例子中的对象 (person) 有三个属性:firstname、lastname 以及 id。
空格和折行无关紧要。声明可横跨多行:
var person={
firstname : "John",
lastname : "Doe",
id : 5566
};
对象属性有两种寻址方式:
name=person.lastname;
name=person["lastname"];
2.6空(Null)和未定义(Undefined)
Undefined 这个值表示变量不含有值。
可以通过将变量的值设置为 null 来清空变量。
cars=null;
person=null;
2.7声明变量类型
当您声明新变量时,可以使用关键词 “new” 来声明其类型:
var carname=new String;
var x= new Number;
var y= new Boolean;
var cars= new Array;
var person= new Object;
JavaScript 变量均为对象。当您声明一个变量时,就创建了一个新的对象。
3.JS函数
函数就是一段可以反复调用的代码块。
函数使用function关键字来定义,还包括一个称为形参(parameter)的标识符列表,这些参数在函数体内像局部变量一样工作。
函数调用会为形参提供实参的值。函数使用它们实参的值来计算返回值,称为该函数调用表达式的值。
如果函数挂载在一个对象上,作为对象的一个属性,就称它为对象的方法。
JavaScript的函数可以嵌套在其他函数中定义,这样它们就可以访问它们被定义时所处的作用域中的任何变量,这就是JavaScript的闭包。
3.1JS函数定义
JavaScript有三种方法,可以定义一个函数。
3.1.1function命令
function name() {}
name是函数名称标识符。函数名称是函数声明语句必需的部分。不过对于函数表达式来说,名称是可选的:如果存在,该名字只存在于函数体内,并指向该函数对象本身。 圆括号:圆括号内可放置0个或多个用逗号隔开的标识符组成的列表,这些标识符就是函数的参数名称。 花括号:可包含0条或多条JavaScript语句。这些语句构成了函数体。一旦调用函数,就会执行这些语句。
3.1.2函数表达式
var f = function(x){
console.log(x);
}
采用函数表达式声明函数时,function命令后面不带有函数名。如果加上函数名,该函数名只在函数体内部有效,在函数体外部无效。
3.1.3Function()
函数定义还可以通过Function()构造函数来定义
var f=new Function('x','y','return x+y');
等价于
var f=function(x,y){
return x+y;
}
注意:如果同一个函数被多次定义(声明),后面的定义(声明)就会覆盖前面的定义(声明)
function f(){
console.log(1);
}
f() //1
function f(){
console.log(2);
}
f() //2
函数可以调用自身,这就是递归(recursion)
function f(x){
if(x>2){
console.log(x);
return f(x-1);
}else{
return 1;
}
}
f(4);
// 4
//3
注意:不能在条件语句中声明函数
3.2函数命名
任何合法的JavaScript标识符都可以用做一个函数的名称。
函数名称通常是动词或以动词为前缀的词组。 通常函数名的第一个字符为小写。
当函数名包含多个单词时,可采取下划线法,比如:like_this()
;也可以采取驼峰法,也就是除了第一个单词之外的单词首字母使用大写字母,比如:likeThis()
;
3.3被提前
就像变量的“被提前”一样,函数声明语句也会“被提前”到外部脚本或外部函数作用域的顶部,所以以这种方式声明的函数,可以被在它定义之前出现的代码所调用。
f()
function f(){}
上面的代码不会报错。
注意:以表达式定义的函数并没有“被提前”。
f();
var f = function (){};
// TypeError: f is not a function
变量其实是分为声明,赋值两部分的,上面的代码等同于下面的形式
var f;
f();
f = function() {};
调用f的时候,f只是被声明了,还没有被赋值,等于undefined,所以会报错。
3.4嵌套函数
在JavaScript中,函数可以嵌套在其他函数里。
function go(){
function play(){}
return play();
}
3.5函数调用
构成函数主体的JavaScript代码在定义时并不会执行,只有调用该函数,它们才会执行。有4种方式调用JavaScript函数:
·作为函数
·作为方法
·作为构造函数
·通过它们的call()和apply()方法间接调用
3.5.1函数调用
f();
3.5.2方法调用
o.f=funciton(){}
o.f();
3.5.3构造函数调用
如果函数或者方法调用之前带有关键字new,它就构成构造函数调用。 凡是没有形参的构造函数调用都可以省略圆括号。
var o=new Object();
var o=new Object;
3.6函数的实参和形参
当调用函数的时候传入的实参比函数声明时指定的形参个数要少,剩下的形参都将设置为undefined值。 为了保持好的适应性,一般应当给参数赋予一个合理的默认值。
function go(x,y){
x = x || 1;
y = y || 2;
}
标识符arguments,其指向实参对象的引用,实参对象是一个类数组对象,可以通过数字下标来访问传入函数的实参值,而不用非要通过名字来得到实参。
function go(x){
console.log(arguments[0]);
console.log(arguments[1]);
}
go(1,2);
//1
//2
arguments有一个length属性,用以标识其所包含元素的个数。
function f(x){
console.log(arguments.length);
}
f(1,2) // 2
注意:arguments并不是真正的数组,它是一个实参对象。每个实参对象都包含以数字为索引的一组元素以及length属性。
通过实参名字来修改实参值的话,通过arguments[]数组也可以获取到更改后的值。
function f(x){
console.log(x); // 1
arguments[0]=null;
console.log(x); // null
}
f(1);
在上面的例子中,arguments[0]和x指代同一个值,修改其中一个的值会影响到另一个。
注意:如果有同名的参数,则取最后出现的那个值。
function f(x,x){
console.log(x);
}
f(1,2) // 2
3.7函数作用域
作用域(scope)指的是变量存在的范围。
Javascript只有两种作用域:一种是全局作用域,变量在整个程序中一直存在,所有地方都可以读取;另一种是函数作用域,变量只在函数内部存在。
在函数外部声明的变量就是全局变量(global variable),它可以在函数内部读取。
var a=1;
function f(){
console.log(a)
}
f() //1
上面的代码中,函数f内部可以读取全局变量a。
在函数内部定义的变量,外部无法读取,称为“局部变量”(local variable)。
函数内部定义的变量,会在该作用域内覆盖同名全局变量。
var a=1;
function f(){
var a=2;
console.log(a);
}
f() //2
a //1
注意:对于var命令来说,局部变量只能在函数内部声明,在其他区块中声明,一律都是全局变量。
函数的执行依赖于变量作用域,这个作用域是在函数定义时决定的,而不是函数调用时决定的。
3.8函数内部的变量提升
与全局作用域一样,函数作用域内部也会产生“变量提升”现象。var命令声明的变量,不管在什么位置,变量声明都会被提升到函数体的头部。
function f(x){
if(x>10){
var a = x -1;
}
}
//等同于
function f(x){
var a;
if(x>10){
a = x - 1;
}
}
3.9函数属性、方法和构造函数
name属性
name属性返回紧跟在function关键字之后的那个函数名。
function f(){}
f.name //f
length属性
函数的length属性是只读属性,代表函数形参的数量,也就是在函数定义时给出的形参个数。
function f(x,y){}
f.length //2
call()方法
语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象。
说明: call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。
apply()方法
语法:apply([thisObj[,argArray]]) 定义:应用某一对象的一个方法,用另一个对象替换当前对象。
说明: 如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。 如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。
toString()方法
函数的toString方法返回函数的源码。
function f(){
return 1;
}
f.toString()
//function f(){
// return 1;
//}
3.10eval命令
eval命令的作用是,将字符串当作语句执行。
eval('var a=1');
a //1
eval没有自己的作用域,都在当前作用域内执行
JavaScript规定,如果使用严格模式,eval内部声明的变量,不会影响到外部作用域。
(function(){
'use strict';
eval('var a=1');
console.log(a); //ReferenceError: a is not defined
})();