JS – 基本语法

JS – 基本语法JavaScript 是一种脚本语言 主要功能是 动态修改 html 页面内容 包括创建 删除 html 页面元素 修改 html 页面元素的内容 外观 位置 大小等 数据类型和变量任何语言都离不开数据类型和变量 虽然 JavaScript 语言是弱类型的语言 但它一样支持变量声明 变量一样存在作用范围 即有局部变量和全局变量之分 定义变量的方式因为 JavaScript 是弱类型的脚本语言 所以使用变量之前 可以无须

JavaScript是一种脚本语言,主要功能是:动态修改html页面内容,包括创建、删除html页面元素、修改html页面元素的内容、外观、位置、大小等。

数据类型和变量

任何语言都离不开数据类型和变量,虽然JavaScript语言是弱类型的语言,但它一样支持变量声明,变量一样存在作用范围,即有局部变量和全局变量之分。

定义变量的方式

因为JavaScript是弱类型的脚本语言,所以使用变量之前,可以无须定义,想使用某个变量直接使用即可,JavaScript支持两种方式来引入变量:

1)隐式定义:直接给变量赋值

2)显示定义:使用var关键字定义变量

隐式定义的方式简单、快捷、需要使用变量时,直接给变量赋值即可。如:

  

执行效果

JS - 基本语法

这里涉及到了在html中使用JavaScript,在html页面中嵌入执行JavaScript代码有两种方式

1)使用javascript:前缀构建执行JavaScript代码的URL。

对于这种方式,所有可以设置URL的地方都可以使用这种方式来执行,当用户触发该URL的时候,javascript:之后的JavaScript代码会获得执行。如:

 run javaScript 

2)使用
元素来包含JavaScript代码,

元素既可以作为
子元素,也可以作为
子元素,上面的代码我们就是使用了第二种方式。

在实际的开发中,为了让html页面和JavaScript脚本更好的分离,我们可以将JavaScript脚本单独保存为一个*.js文件,在html页面倒入该*.js文件即可。导入的语法方式如下:

src指定了JavaScript脚本文件所在的URL。OK,说了这么多,继续我们的定义变量。

显示声明的方式说采用var关键字声明变量,声明时变量可以没有初始值,变量的变量数据类型是不确定的。当第一次给变量赋值时,变量的数据类型菜确定下来,而且使用过程中数据类型也可随意改变。

与其它变成语言类似,JavaScript也允许一次定义多个变量,并可以指定初始值,如:

var a, b=0, c;


类型转换

Javascript支持自动类型转换,并且类型转换的功能非常强大。如:

 

执行结果

JS - 基本语法

上面的代码中a是字符串,其值为3.145,让a和数值执行减法,则自动执行算术运算,并将a的类型转换为数值;让a和数值执行加法,则a的值转换为字符串,使用加号相当于给字符串进行拼接操作,这就是自动类型转换。

虽然自动类型转换非常方便,但是持续的可读性非常差,而且有时候我们就是希望让字符串和数值进行加法运算,那么就需要使用强制类型转换了。JavaScript提供了以下几个函数来执行强制类型转换。

toString():将布尔值、数值等转换为字符串

parseInt():将字符串、布尔值等转换为整数

parseFloat():将字符串、布尔值等转换为浮点数

如:我们想要让“3.145”+2执行表达式之后结果为5.145

 

但是并不是所有的转换都是成功的,对于包含其它字符的字符串,将转换为NaN。对于使用toString()函数将各种类型的值向字符串转换,结果全部是object。


变量

JavaScript是弱类型语言,同一个变量可以一会存储数值,一会存储字符串。变量有个重要的概念:作用范围。根据变量定义的作用范围不同,变量有全局变量和局部变量之分。直接定义的变量是全局变量,全局变量可以被所有的脚本访问,在函数内定义的变量为局部变量,局部变量只能够在函数内有效,如果全局变量和局部变量有相同的变量名,则局部变量将覆盖全局变量。

  

上面局部变量test覆盖了全局变量,所以执行方法checkScope()之后,会alert局部变量的值。注意:JavaScript的变量没有块范围,比如:

执行结果

JS - 基本语法

即k的值为10,j的值为5,是不是有点奇怪,k和j怎么会有值?因为JavaScript的变量没有块范围,所以变量i,j,k的作用域是整个函数内而不是在对应的块范围内。也正是因为变量没有块范围,所以有时候会出现一些奇怪的结果,在看个例子:

 

执行结果:

undefined

局部变量

第一次使用scope并没有使用全局变量而是undefined,第二次使用局部变量,因为

1、定义全局变量scope

2、使用scope变量,但并不是全局变量,因为全局变量被test函数中scope被覆盖了,局部变量在整体test函数内部都是有效的,但是此时scope还没有被赋值,所以会输出undefined。

3、定义局部变量并赋值,所以输出局部变量。

注意:定义变量使用var和不使用var是有差异的,如果使用var定义变量,那么程序会强制定义一个新变量。如果没有使用var定义变量,系统会优先在当前上下文中搜索是否存在该变量,只有在该变量不存在的前提下,系统才会重新定义一个新变量。


基本数据类型

JavaScript的基本数据类型有5个:

数值类型:包含整数和浮点数

布尔类型:只有true或false两个值

字符串类型:字符串变量必须使用引号括起来,引号可以是单引号,也可以是双引号

undefined类型:专门用来确定一个已经创建但是没有初值的变量

null类型:用于表达某个变量的值为空

数值类型

JavaScript的数值类型不仅包括所有的整型变量也包括所有的浮点型变量,JavaScript语言中的数值都以IEEE 754-1985双精度浮点数格式保存。JavaScript中的数值类型非常丰富,完全支持科学计数法表示,格式如下:

 
   
     E 
     
   

这种形式的值为:num1*10的num2次方。E为间隔符号,E不区分大小写.

执行结果

JS - 基本语法

字符串类型

JavaScript的字符串必须是要引号,此处的引号既可以是单引号,也可以是双引号。例如:

a = 'Hello JavaScript' b = "Hello JavaScript"

上面a,b两个变量完全相等,JavaScript没有字符类型。JavaScript以String内建类来表示字符串,String类里包含了一系列方法操作字符串:

String():类似于面向对象语言的构造器,使用该方法可以构造一个字符串

charAt():获取字符串特定索引处的字符

charCodeAt():返回字符串中特定索引处的字符所对应的Unicode值

toUpperCase():返回字符串的长度,JavaScript中文字符算一个字符

toLowerCase():将字符串的所有字母转换为大写字母

fromCharCode():静态方法,直接通过String类调用该方法,将一系列Unicode值转换为字符串

indexOf():返回字符串中特定字符串第一次出现的位置

lastIndexOf():返回字符串中特定字符串最后一次出现的位置

substring():返回字符串的某个子字符串

slice():返回字符串的某个子字符串,功能比substring更强大支持负数参数

match():使用正则表达式搜索目标子字符串

search():使用正则表达式是谁目标子字符串

concat():用于将多个字符串拼接成为一个字符串

split():将某个字符串分割成为多个字符串,可以指定分割符号

replace():将字符串中某个子串以特定字符串替代

var a = "abc"; var b = a.length; var c = String.fromCharCode(97,98,99); console.log(b + "---" + a.charAt(2) + "---" + a.charCodeAt(2) + "---" + c);

执行如下:

3---c---99---abc

布尔类型

布尔类型的值只有两个:true和false,通常用于逻辑判断。

var numberOne = 200 var numberTwo = 100 if (numberOne > numberTwo) { console.log(numberOne); } else { console.log(numberTwo); }

undefined和null

undefined类型的值只有一个undefined,该值用于表示某个变量不存在,或者没有为其分配值,也用于表示对象的属性不存在。null用于表示该变量的值为空。undefined于null之间的差别在于:undefined表示没有为变量设置值或者不存在而null表示变量有值,只是其值为null。注意:很多时候null和undefined是相等的,即null==undefined,如果要区分,那么需要使用===进行判断。

var x , y = null; if (x === undefined) { console.log("声明变量后默认值为undefined"); } if (x === null) { console.log("声明变量后默认值为null"); } if (x == y) { console.log("x: (undefined) == y: (null)"); } if (String.xy === undefined) { console.log("不存在的属性值默认是undefined"); } if (x === y) { console.log("x等于y"); } else { console.log("x不等于y"); }

执行结果:

声明变量后默认值为undefined
x: (undefined) == y: (null)
不存在的属性值默认是undefined





x不等于y


复合类型

复合类型是由多个基本数据类型(也可以包括复合类型)组成的数据体,JavaScript中的复合类型大致有如下3种:

Object:对象

Array:数组

Function:函数

对象

对象是一系列命名变量、函数的集合。其中命名变量的类型既可以是基本数据类型,而可以是复合类型。对象中的命名变量称为属性,而对象中的函数称为方法。对象访问属性和函数的方法都是使用“.”(点)实现。JavaScript是基于对象的脚本语言,它提供了大量的内置对象供用户使用,JavaScript提供了如下常用的内置类。

Array:数组类

Date:日期类

Error:错误类

Function:函数类

Math:数学类,该对象包含相当多的执行数学运算的方法

Number:数值类

Object:对象类

String:字符串类


数组

数组是一系列的变量,于其他强类型语言不同的是,JavaScript中数组元素的类型可以不同。定义应该数组由如下3种方法:

var a = [3, 5, 20]; // 定义的时候初始化数组 var b = []; // 创建一个空数组 var c = new Array(); // 创建一个空数组

简单使用

var a = [3, 5, 20]; // 定义的时候初始化数组 var b = []; // 创建一个空数组 var c = new Array(); // 创建一个空数组 b[0] = "你好"; b[1] = 100; b[2] = true; c[3] = true; console.log(a + "\n" + b + "\n" + c);

执行结果

3,5,20
你好,100,true



,,,true

JavaScript作为动态、弱类型语言,归纳起来,其数组有如下3个特征:

1)JavaScript的数组长度可变,数组长度总等于所有元素索引最大值+1

2)同一个数组中的元素类型可以互不相同

3)访问数组元素时不会产生数组越界,访问并未赋值的数组元素时,该元素的值为undefined。


函数

函数可以包含一段可执行的代码,也可以接收调用者传入参数,正如弱类型语言一样,JavaScript的函数声明中,参数列表不需要数据类型声明,函数的返回值也不需要数据类型声明,函数定义的语法格式如下:

function functionName(param1, param2,...) { }

简单使用

function judgeAge(age) { if (age > 60) { console.log("老人"); } else if (age > 40 ) { console.log("中年人"); } else if (age > 15) { console.log("年轻人"); } else { console.log("儿童"); } } judgeAge(26); //年轻人

虽然调用judgeAge(26)程序能够正常运行,但是如果传入的不是数值那么程序就会有问题,所以最好先对参数类型进行判断,判断变量的数据类型可以使用typeof运算符,该函数用于返回变量的数据类型。

function judgeAge(age) { if (typeof age === "number") { if (age > 60) { console.log("老人"); } else if (age > 40 ) { console.log("中年人"); } else if (age > 15) { console.log("年轻人"); } else { console.log("儿童"); } } else { console.log("must be number") } }

运算符

JavaScript提供了相当丰富的运算符,包括了赋值运算符、算术运算符、逻辑运算符、位运算符等。

赋值运算符

赋值运算符用于位变量指定变量值,于Java, C类似,也使用“=”作为赋值运算符,通常使用赋值运算符将一个常量值赋给变量。

var a = "JavaScript" var pi = 3.14 var visited = true

也可以使用赋值运算符将一个变量的值赋给另一个变量

var b = a;

算术运算符

JavaScript支持所有的基本算数运算符:

1)加法运算符

var a = 5; var b = 10; var sum = a + b;

2)减法运算符

var a = 5; var b = 10; var sub = b - a;

3)乘法运算符

var a = 5; var b = 10; var sub = b * a;

4)除法运算符

var a = 5; var b = 10; var sub = b / a;

5)取余运算符

var a = 5; var b = 10; var sub = b % a;

6)自加(++)运算符

++既可以出现在操作数的左边也可以出现早操作数的右边,但是效果不一样,跟c语言中的自增效果是一样的

var a = 5; var b = 10; var sum = b++ + a; console.log(sum); // 15

++在前

var a = 5; var b = 10; var sum = ++b + a; console.log(sum); // 16

7)自减(--)

--运算符在前

var a = 5; var b = 10; var sum = --b + a; console.log(sum); // 14

--运算符在后

var a = 5; var b = 10; var sum = b-- + a; console.log(sum); // 15

位运算符

JavaScript支持的位运算符有如下几种:

&:按位与

|:按位或

~:按位非

^:按位异或

<<:左移位运算符

>>:右移位运算符

>>>:无符号右移位运算符

简单使用

console.log(5 & 9); //1 5 -> 00000101 9 -> 00001001 = 00000001 

比较运算符

比较运算符用于判断两个变量或者常量的大小,比较运算的结果是一个布尔值,JavaScript支持的比较运算符如下:

1)>:大于,如果前面变量的值大于后面变量的值,则返回true

2)>=:大于等于,如果前面变量的值大于等于后面变量的值,则返回true

3)<:小于,如果前面变量的值小于后面变量的值,则返回true

4)<=:小于等于,如果前面变量的值小于等于后面变量的值,则返回true

5)==:等于,如果前面两个变量的值相同,则返回true

6)!=:不等于,如果前后两个变量的值不相等,则返回true

7)===:严格等于,前后两个变量的值必须相同并且类型也相同才会返回true。

8)!==:严格不等于,如果前后两个变量的值不相等,或者数据类型不同,都江返回true.

if (5 == "5") { console.log("==") } if (5 === "5") { console.log("===") } else { console.log("not equal") }

执行结果:

==
not equal

逻辑运算符

逻辑运算符用于操作两个布尔值的变量或者常量,主要有以下3个:

&&:与,必须前后两个操作数都为true才返回true,否则返回false

||:或,只要两个操作法中有一个为true,就可以返回true,否则返回false

!:非,只操作一个操作数,如果操作数为true,则返回false,如果操作数为false,则返回true

var a = 10; var b = 12; if (a > 10 || b < 14) { console.log("true") }


三目运算符

三目运算符的格式如下:

(expression) ? if-true-statement : if-false-statement;

运算规则很简单,先对逻辑表达式expression求值,如果逻辑表达式返回true,则执行第二部分的语句,如果逻辑表达式返回false,则返回第三部分的语句。

var a = 10; var b = 12; var result = (a > 10) ? a : b; console.log(result) // 12


typeof和instance运算符

typeof前面简单了解过,用于判断某个变量的数据类型,它既可以作为函数来使用,例如:typeof(a),返回变量a的数据类型,也可以作为一个运算符来使用,例如:typeof a 可以返回变量a的数据类型。不同类型参数使用typeof运算符的返回值类型如下:

undefined值:object

null值:object

布尔型值:boolean

数字型值:number

字符串值:string

对象:object

函数:function

var a = 5; //number var b = true; //boolean var str = "hello"; // string console.log(typeof(a) + "\n" + typeof(b) + "\n" + typeof(str));

与typeof类似的运算符还有instanceof,该运算符用于判断某个变量是否为指定类的实例,如果是,则返回true,否则返回false。

var a = [3]; console.log(a instanceof Array); //true console.log(a instanceof Object); //true,JS中所有类都是object的子类

逗号运算符

逗号运算符允许将多个表达式排在一起,整个表达式返回最右边表达式的值。

var a, b, c, d; a = (b = 5, c = 7, d = 10); console.log(a); // 10


void运算符

void运算符用于强制指定表达式不会返回值

var a, b, c, d; a = (b = 5, c = 7, d = 10); console.log(a); // undefined



语句

语句时JavaScript的基本执行单位.JavaScript要求所有的语句都以分号(;)结束。语句既可以是简单的赋值语句,也可以是算法运算语句,还可以是逻辑运算语句。除此之外还有一些特殊的语句:

异常抛出语句

JavaScript支持异常处理,支持手动抛出异常,JavaScript的所有异常都是Error对象,当JavaScript需要抛出异常总是通过throw语句抛出error对像,语法如下:

throw new Error(errorString);

JavaScript既允许再代码执行的过程中抛出异常,也允许再函数定义中抛出异常,在代码执行过程中,一旦遇到异常,立即寻找对应的异常捕获块(catch块),如果没有对应的异常捕获块,异常将传播给浏览器,程序非正常中止。

for (var i = 0; i < 10; i++) { if (i > 4) { throw new Error("用户自定义错误"); } }

捕获异常

当程序异常出现时,这种异常不管是用户手动抛出的异常还是系统本身的异常,都可以使用catch捕获异常,JavaScript代码运行中一旦出现异常,程序就跳转到对应的catch块,语法如下:

try { statement } catch { statement } finally { statement }

上面的捕获语句,finally块是可以省略的,如果指定了finally块,那么finally代码块就会总获得执行的机会。

try { for (var i = 0; i < 10; i++) { console.log(i); if (i>5) { throw new Error("error"); } } } catch (error) { console.log("system wrong: " + error.message); } finally { console.log("finally"); }

执行结果:

0
1
2
3
4
5
6
system wrong: error















finally

简单总结:

1)JavaScript只有一个异常类,Error,无须在定义函数时声明抛出该异常,所以没有throw关键字

2)JavaScript是弱类型语言,所以catch语句后括号里的异常实例无须声明类型

3)JavaScript只有一个异常类,所以try块最多只能有一个catch块

4)获取异常的描述信息是通过异常对象message属性,而不是通过getMessage()方法实现


with语句

with语句的作用是避免重复书写同一个对象。语法格式如下

with(object) { statements }

如果with后的代码块只有一行语句,则可以省略花括号。


流程控制

JavaScript支持的流程控制丰富,有基本的分支语句if,if-else,也有循环语句for,while,for-in等

分支语句

分支语句主要有if和switch语句,其中if有三种格式:

// 形式1 if (expression) { statement } // 形式2 if (expression) { statement } else { statement } //形式3 if (expression) { statement } else if (expression) { statement } else { statement }

通常情况下不要省略if、else、else if后执行块的花括号,但是如果语句执行块只有一行代码时,则可以省略花括号。

var a = 5; if (a > 4) console.log("a大于4"); else console.log("a小于4");

switch语句的语法如下:

switch (expression) { case condition 1: statemnt break; case condition 2: statemnt break; default: statemnt }

先执行expression表达式,然后依次匹配条件condition1,condition2,遇到了匹配的条件就执行相应的代码,如果前面的条件都没有正常匹配,则执行default后的执行体。

function inputScore(score) { switch (score) { case 'A': console.log("优秀"); break; case 'B': console.log("良好"); break; case 'C': console.log("及格"); break; case 'D': console.log("不及格"); break; default: console.log("error"); } }

注意2点:

1)JavaScript的switch语句可以省略case块后面的break;如果省略了,那么就会一直执行case之后的代码,直到遇见break语句为止

2)switch语句的条件变量不仅可以是数值类型也可以是字符串类型。


while语句

while语句的语法格式如下:

while (expression) { statement }

当循环体只有一行语句时,循环体的花括号可以省略,while循环语句的作用是:先判断expression逻辑表达式的值,当expression表达式的值为true时,执行循环体,如果微false则结束循环。但是要注意:一定要有false的时候,不然会造成死循环。


do-while循环

do-while循环跟while的区别在于:while是先判断循环条件,只有条件为真才会执行循环体,但是do-while则先执行循环体,然后判断循环条件,如果条件为真,则执行下一次循环。否则中止循环。

do { statement } while (expression)

for循环

for循环是常用的循环语句,大部分情况下,for循环可以代替while循环、do-while循环。基本语法格式如下:

for (var i = 0; i < Things.length; i++) { }

循环中两个分号分开了三个语句,其中第一个语句是循环的初始化语句,每个循环语句只会执行一次,而且完全可以省略,因为初始化语句可以放在循环语句之前完成,第二个语句是一个逻辑表达式,用于判断是否执行下一次循环,第三个语句是循环体执行完后最后执行的语句。


for in 循环

for in循环的本质是一种foreach循环,它主要有两个作用:

1)遍历数组里的所有数组元素

2)遍历JavaScript对象的所有属性

语法格式:

for (index in object) { statement }

如果循环体只有一行代码,则可以省略循环体的花括号,当遍历数组时,for in 循环的循环计数器是数组元素的索引值。

break和continue

break和continue都可用于中止循环,区别在于continue只是中止本次循环,接着开始下一次循环,而break则是完全中止整个循环,开始执行循环体后面的语句。


函数

JavaScript是一种基于对象的脚本语言,JavaScript代码复用的单位是函数,但它的函数比结构化程序设计语言的函数功能更加丰富,JavaScript语言中的函数是“一等公民”,它可以独立存在,而且JavaScript的函数完全可以作为一个类使用,而且它还是该类唯一的构造器,函数本身也是一个对象,函数本身是Function实例。

定义函数的3种方式

JavaScript是弱类型语言,因此定义函数时,既不需要声明函数的返回值类型,也不需要声明函数的参数类型。

定义命名函数

定义命名函数的语法格式:

function functionName(parameter-list) { statements }
function greeting(name) { console.log("hello " + name); } greeting("Jack"); //hello Jack

函数最大作用是提供代码复用,所以应该将需要重复使用的代码块定义成为函数,提供更好的代码复用。函数可以有返回值也可以没有返回值,函数的返回值使用return语句返回,在函数的运行过程中,一旦遇到了第一条return语句,函数就返回返回值,函数运行结束

定义匿名函数

JavaScript提供了定义匿名函数的方式,语法格式如下:

function(parameter list) { statements };

这种函数定义语法无须指定函数名,而是将参数列表紧跟function关键字,在函数定义语法的最后不要忘记紧跟分号(;)。当通过这种语法格式定义函数之后,实际上就是定义了一个函数对象(即Function实例),接下来可以将这个对象赋给另一个变量,之后可以通过变量来执行调用函数。

var f = function(name) { console.log(name); }; f("Jack"); //Jack

使用Function类匿名函数

JavaScript提供了Function类,该类可以用于定义函数,Function类的构造器的参数个数可以不受限制,Function可以接受一系列的字符串参数,其中最后一个字符参数是函数的执行体,执行体的各语句可以以分号(;)隔开,而前面的各字符串参数则是函数的参数。

var fun = new Function('name', "console.log(name);"); fun('hua');

上面代码使用了new Function语法定义了一个匿名函数,并将匿名函数赋给fun变量,从而允许通过fun来访问匿名函数。调用Function类的构造器来创建函数虽然能够明确地表示创建一个Function对象,但由于Function()构造器的最后一个字符代表函数执行体,当函数执行体的语句很多时,Function的最后一个参数将变得十分臃肿,因此可读性也差。

局部变量和局部函数

在函数里定义的变量成为局部变量,在函数外定义的变量成为全局变量,如果局部变量和全局变量的变量名相同,则局部变量会覆盖全局变量,局部变量只能够在函数里访问,而全局变量可以在所有的函数里面访问。局部函数即在函数里面定义的函数,并且在在函数内部有效。

function outer() { function inner1() { console.log("inner1"); } function inner2() { console.log("innner2"); } inner1(); inner2(); } outer(); // inner1 innner2

函数、方法、对象和类

函数:就像JavaScript的方法一样,这个函数可以被调用,JavaScript的函数不仅是一个函数更是一个类

对象:定义一个函数时,系统也会创建一个对象,该对象是Function类的实例

方法:定义一个函数时,该函数通常都会附加给某个对象,作为该对象的方法

类:在定义函数的同时,也得到了一个与函数同名的类

下面程序定义了一个Person函数,也就是定义了一个Person类,该Person函数也会作为Person类的唯一构造器。

function Person(name, age) { this.name = name; // 将参数name值赋值给name属性 this.age = age; // 将参数age赋值给age属性 this.info = function() // 为info创建一个匿名函数 { console.log("My name is: " + this.name); console.log("age = " + this.age); }; } var p = new Person("Jack", 26); p.info(); // My name is: Jack // age = 26

上面程序中使用了this关键字,被this关键字所修饰的变量不再是局部变量,它是该函数的实例属性。而且info属性是一个函数,即JavaScript定义的函数可以被赋值给对象,作为对象的方法,如果没有明确指定赋值的对象将被赋值到window对象上,作为window对象的方法。


函数的实例属性和类属性

前面也讲到了JavaScript函数不仅仅是一个函数,而且是一个类,该函数还是此类唯一的构造器,只要在调用函数时使用new关键字,就可以返回一个Object,这个Object不是函数的返回值,而是函数本身产生的对象。因此在JavaScript中定义的变量不仅有局部变量,还有实例属性和类属性两种。根据函数中声明变量的方式,函数中的变量有3种:

局部变量:在函数中以普通方式声明的变量,包括以var或者不加任何前缀声明的变量

实例属性:在函数中以this前缀修饰变量

类属性:在函数中以函数名为前缀修饰变量

function Person(name, age) { this.name = name; // 将参数name值赋值给name属性 Person.age = age; // 将参数age赋值给age属性 this.info = function() // 为info创建一个匿名函数 { console.log("My name is: " + this.name); console.log("age1 = " + this.age); console.log("age2 = " + Person.age); }; } var p = new Person("Jack", 26); p.info(); p.age = "30"; p.info(); // result: My name is: Jack age1 = undefined age2 = 26 My name is: Jack age1 = 30 age2 = 26

可以看到刚刚开始没有实力属性age,但是当我们执行p.age = "30";之后,自动为对象增加了age属性,这是因为JavaScript是动态语言,它允许为对象增加属性和方法,当我们直接为对象的某个属性赋值时,即可视为给对象增加属性。


调用函数的3种方式

定义一个函数之后,JavaScript提供了3种方式来调用函数。

直接调用函数

直接调用函数是最常见的方式,这种方式直接以函数附加的对象作为调用者,在函数括号内传入参数来调用函数,前面已经大量使用了。

以call()方法来调用函数

直接调用函数的方式简单,但是不够灵活,有时候调用函数时需要动态地传入一个函数引用,此时为了动态的调用函数,就需要使用call()方法来调用函数。

假如我们需要定义一个形如each(array, fn)的函数,这个函数可以自动迭代处理array数组元素,而fn函数则负责对数组元素进行处理,此时需要在each函数中调用fn函数,但目前fn函数并未确定,因此无法采用直接调用的方式来调用fn函数,需要通过call()方法来调用函数。

var each = function(array, fn) { for (var index in array) { fn.call(null, index, array[index]); } }; each([5, 10 ,3], function(index, element) { console.log("第" + index + "个元素是:" + element + "\n"); });

上面的代码使用call()动态的调用函数,call()方法的语法格式如下:

函数引用.函数(调用者,参数1,参数2...),

这里也可以得到直接调用函数与通过call()方法调用函数的关系:

调用者.函数(参数1,参数2...) = 函数.call(调用者,参数1,参数2...)

apply()方法调用函数

apply()方法与call()方法功能基本相似,它们都可以动态地调用函数。apply()与call()的区别如下:

1)通过call()调用函数时,必须在括号中详细的列出每个参数

2)通过apply()动态地调用函数时,可以在括号中以arguments来代表所有参数。

var example = function (num1, num2) { myfun.apply(this, arguments); }; example(20, 40); // 直接调用 example.apply(null, [10, 15]); // 使用apply方法调用函数


函数的参数

对于基本类型参数,JavaScript采用值传递的方式,当通过实参调用函数时,传入函数里的并不是实参本身,而是实参的副本,因此在函数中修改参数值并不会对实参有任何影响。

function change(paramter) { paramter = 20; console.log(paramter); //20 } var x = 10; change(x); console.log(x); //10

对于复合类型的参数,实际上采用的依然是值传递的方式

function changeAge(person) { person.age = 10; console.log(person.age); // 10 person = null; // 将person对象设置为null } var person = { age: 5}; // 使用JSON语言创建对象 changeAge(person); console.log(person.age); // 10 console.log(person); // { age: 10 }

上面代码和结果可知,person对象的age属性其值是发生了改变,但是person对象被设置为null之后却依然存在,这表明person对象本身并没有被传入函数中,传入的只是person对象的副本而已,这里可能很容易让人混淆。

复合类型的变量本身并未持有对象本身,复合类型的变量只是一个引用,该引用指向实际的JavaScript对象,当把person复合类型的变量传入changeAge()函数时,传入的依然是person变量的副本,只是该副本和原person变量指向同一个JavaScript对象,因此不管是修改副本所引用的JavaScript对象,还是修改person变量所引用的JavaScript对象,实际上修改的是同一个对象。


空参数

function changeAge(person) { if (typeof person == 'object') { person.age = 10; console.log(person.age); // 10 } else { console.log("参数类型不符合"); } } changeAge(); //参数类型不符合

由上面的代码可知,函数声明中包含了一个参数,但是调用函数时并没有传入任何参数,这种情况对于强类型语言,如:Java,C那是绝对不允许的,但是对于JavaScript却没有任何语法问题,因为JavaScript会将没有传入实参的参数值自动设置为undefined。

由于JavaScript调用函数时对传入的实参并没有要求,即使定义函数时声明了多个形参,调用函数时也并不强制要求传入相匹配的实参。因此JavaScript没有所谓的函数“重载”,对于JavaScript而言函数名就是唯一的标识。








版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/178829.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午4:26
下一篇 2026年3月26日 下午4:27


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号