沧州做网站哪家好,网页创意与设计50例,凡科邮箱手机登录,双语企业网站JavaScript 函数定义
JavaScript 使用关键字 function 定义函数。
函数可以通过声明定义#xff0c;也可以是一个表达式。
函数声明
在之前的教程中#xff0c;你已经了解了函数声明的语法 :
function functionName(parameters) {执行的代码
}函数声明后不会立即执行也可以是一个表达式。
函数声明
在之前的教程中你已经了解了函数声明的语法 :
function functionName(parameters) {执行的代码
}函数声明后不会立即执行会在我们需要的时候调用到。
function myFunction(a, b) {return a * b;
}分号是用来分隔可执行JavaScript语句。 由于函数声明不是一个可执行语句所以不以分号结束。 函数表达式
JavaScript 函数可以通过一个表达式定义。
函数表达式可以存储在变量中
var x function (a, b) {return a * b};在函数表达式存储在变量后变量也可作为一个函数使用
var x function (a, b) {return a * b};
var z x(4, 3);以上函数实际上是一个 匿名函数 (函数没有名称)。
函数存储在变量中不需要函数名称通常通过变量名来调用。 上述函数以分号结尾因为它是一个执行语句。 Function() 构造函数
在以上实例中我们了解到函数通过关键字 function 定义。
函数同样可以通过内置的 JavaScript 函数构造器Function()定义。
var myFunction new Function(a, b, return a * b);var x myFunction(4, 3);实际上你不必使用构造函数。上面实例可以写成
var myFunction function (a, b) {return a * b};var x myFunction(4, 3);在 JavaScript 中很多时候你需要避免使用 new 关键字。 函数提升Hoisting
在之前的教程中我们已经了解了 “hoisting(提升)”。
提升Hoisting是 JavaScript 默认将当前作用域提升到前面去的行为。
提升Hoisting应用在变量的声明与函数的声明。
因此函数可以在声明之前调用
myFunction(5);function myFunction(y) {return y * y;
}使用表达式定义函数时无法提升。
自调用函数
函数表达式可以 “自调用”。
自调用表达式会自动调用。
如果表达式后面紧跟 () 则会自动调用。
不能自调用声明的函数。
通过添加括号来说明它是一个函数表达式
(function () {var x Hello!!; // 我将调用自己
})();以上函数实际上是一个 匿名自我调用的函数 (没有函数名)。
函数可作为一个值使用
JavaScript 函数作为一个值使用
function myFunction(a, b) {return a * b;
}var x myFunction(4, 3);JavaScript 函数可作为表达式使用
function myFunction(a, b) {return a * b;
}var x myFunction(4, 3) * 2;函数是对象
在 JavaScript 中使用 typeof 操作符判断函数类型将返回 “function” 。
但是JavaScript 函数描述为一个对象更加准确。
JavaScript 函数有 属性 和 方法。
arguments.length 属性返回函数调用过程接收到的参数个数
function myFunction(a, b) {return arguments.length;
}toString() 方法将函数作为一个字符串返回:
function myFunction(a, b) {return a * b;
}var txt myFunction.toString();箭头函数
ES6 新增了箭头函数。
箭头函数表达式的语法比普通函数表达式更简洁。
(参数1, 参数2, …, 参数N) { 函数声明 }
(参数1, 参数2, …, 参数N) 表达式(单一) // 相当于(参数1, 参数2, …, 参数N) { return 表达式; }
当只有一个参数时圆括号是可选的
(单一参数) {函数声明} 单一参数 {函数声明}
没有参数的函数应该写成一对圆括号:
() {函数声明}
// ES5
var x function(x, y) {return x * y;
}// ES6
const x (x, y) x * y;有的箭头函数都没有自己的 this。 不适合定义一个 对象的方法。
当我们使用箭头函数的时候箭头函数会默认帮我们绑定外层 this 的值所以在箭头函数中 this 的值和外层的 this 是一样的。
箭头函数是不能提升的所以需要在使用之前定义。
使用 const 比使用 var 更安全因为函数表达式始终是一个常量。
如果函数部分只是一个语句则可以省略 return 关键字和大括号 {}这样做是一个比较好的习惯:
const x (x, y) { return x * y };注意IE11 及更早 IE 版本不支持箭头函数。
JavaScript 函数参数
JavaScript 函数对参数的值没有进行任何的检查。
函数显式参数(Parameters)与隐式参数(Arguments)
在先前的教程中我们已经学习了函数的显式参数:
functionName(parameter1, parameter2, parameter3) {// 要执行的代码……
}函数显式参数在函数定义时列出。
函数隐式参数在函数调用时传递给函数真正的值。
参数规则
JavaScript 函数定义显式参数时没有指定数据类型。
JavaScript 函数对隐式参数没有进行类型检测。
JavaScript 函数对隐式参数的个数没有进行检测。
默认参数
ES5 中如果函数在调用时未提供隐式参数参数会默认设置为 undefined
有时这是可以接受的但是建议最好为参数设置一个默认值
function myFunction(x, y) {if (y undefined) {y 0;}
}或者更简单的方式
function myFunction(x, y) {y y || 0;
}如果 y 已经定义y || 0 返回 y因为 y 是 true否则返回 0因为 undefined 为 false。 如果函数调用时设置了过多的参数参数将无法被引用因为无法找到对应的参数名。 只能使用 arguments 对象来调用。
ES6 函数可以自带参数
ES6 支持函数带有默认参数就判断 undefined 和 || 的操作
function myFunction(x, y 10) {// y is 10 if not passed or undefinedreturn x y;
}myFunction(0, 2) // 输出 2
myFunction(5); // 输出 15, y 参数的默认值arguments 对象
JavaScript 函数有个内置的对象 arguments 对象。
arguments 对象包含了函数调用的参数数组。
通过这种方式你可以很方便的找到最大的一个参数的值
x findMax(1, 123, 500, 115, 44, 88);function findMax() {var i, max arguments[0];if(arguments.length 2) return max;for (i 0; i arguments.length; i) {if (arguments[i] max) {max arguments[i];}}return max;
}或者创建一个函数用来统计所有数值的和
x sumAll(1, 123, 500, 115, 44, 88);function sumAll() {var i, sum 0;for (i 0; i arguments.length; i) {sum arguments[i];}return sum;
}通过值传递参数
在函数中调用的参数是函数的隐式参数。
JavaScript 隐式参数通过值来传递函数仅仅只是获取值。
如果函数修改参数的值不会修改显式参数的初始值在函数外定义。
隐式参数的改变在函数外是不可见的。
通过对象传递参数
在JavaScript中可以引用对象的值。
因此我们在函数内部修改对象的属性就会修改其初始的值。
修改对象属性可作用于函数外部全局变量。
修改对象属性在函数外是可见的。
JavaScript 函数调用
JavaScript 函数有 4 种调用方式。
每种方式的不同在于 this 的初始化。
this 关键字
一般而言在Javascript中this指向函数执行时的当前对象。 注意 this 是保留关键字你不能修改 this 的值。 调用 JavaScript 函数
在之前的章节中我们已经学会了如何创建函数。
函数中的代码在函数被调用后执行。
作为一个函数调用
function myFunction(a, b) {return a * b;
}
myFunction(10, 2); // myFunction(10, 2) 返回 20以上函数不属于任何对象。但是在 JavaScript 中它始终是默认的全局对象。
在 HTML 中默认的全局对象是 HTML 页面本身所以函数是属于 HTML 页面。
在浏览器中的页面对象是浏览器窗口(window 对象)。以上函数会自动变为 window 对象的函数。
myFunction() 和 window.myFunction() 是一样的
function myFunction(a, b) {return a * b;
}
window.myFunction(10, 2); // window.myFunction(10, 2) 返回 20 这是调用 JavaScript 函数常用的方法 但不是良好的编程习惯 全局变量方法或函数容易造成命名冲突的bug。 全局对象
当函数没有被自身的对象调用时 this 的值就会变成全局对象。
在 web 浏览器中全局对象是浏览器窗口window 对象。
该实例返回 this 的值是 window 对象:
function myFunction() {return this;
}
myFunction(); // 返回 window 对象函数作为全局对象调用会使 this 的值成为全局对象。 使用 window 对象作为一个变量容易造成程序崩溃。 函数作为方法调用
在 JavaScript 中你可以将函数定义为对象的方法。
以下实例创建了一个对象 (myObject), 对象有两个属性 (firstName 和 lastName), 及一个方法 (fullName):
var myObject {firstName:John,lastName: Doe,fullName: function () {return this.firstName this.lastName;}
}
myObject.fullName(); // 返回 John DoefullName 方法是一个函数。函数属于对象。 myObject 是函数的所有者。
this对象拥有 JavaScript 代码。实例中 this 的值为 myObject 对象。
测试以下修改 fullName 方法并返回 this 值:
var myObject {firstName:John,lastName: Doe,fullName: function () {return this;}
}
myObject.fullName(); // 返回 [object Object] (所有者对象)函数作为对象方法调用会使得 this 的值成为对象本身。 使用构造函数调用函数 如果函数调用前使用了 new 关键字, 则是调用了构造函数。
这看起来就像创建了新的函数但实际上 JavaScript 函数是重新创建的对象
// 构造函数:
function myFunction(arg1, arg2) {this.firstName arg1;this.lastName arg2;
}// This creates a new object
var x new myFunction(John,Doe);
x.firstName; // 返回 John构造函数的调用会创建一个新的对象。新对象会继承构造函数的属性和方法。 构造函数中 this 关键字没有任何的值。 this 的值在函数调用实例化对象(new object)时创建。 作为函数方法调用函数
在 JavaScript 中, 函数是对象。JavaScript 函数有它的属性和方法。
call() 和 apply() 是预定义的函数方法。 两个方法可用于调用函数两个方法的第一个参数必须是对象本身。
function myFunction(a, b) {return a * b;
}
myObject myFunction.call(myObject, 10, 2); // 返回 20function myFunction(a, b) {return a * b;
}
myArray [10, 2];
myObject myFunction.apply(myObject, myArray); // 返回 20两个方法都使用了对象本身作为第一个参数。 两者的区别在于第二个参数 apply传入的是一个参数数组也就是将多个参数组合成为一个数组传入而call则作为call的参数传入从第二个参数开始。
在 JavaScript 严格模式(strict mode)下, 在调用函数时第一个参数会成为 this 的值 即使该参数不是一个对象。
在 JavaScript 非严格模式(non-strict mode)下, 如果第一个参数的值是 null 或 undefined, 它将使用全局对象替代。 通过 call() 或 apply() 方法你可以设置 this 的值, 且作为已存在对象的新方法调用。 JavaScript 闭包
JavaScript 变量可以是局部变量或全局变量。
私有变量可以用到闭包。
全局变量
函数可以访问由函数内部定义的变量如
function myFunction() {var a 4;return a * a;
}函数也可以访问函数外部定义的变量如
var a 4;
function myFunction() {return a * a;
}后面一个实例中 a 是一个 全局 变量。
在web页面中全局变量属于 window 对象。
全局变量可应用于页面上的所有脚本。
在第一个实例中 a 是一个 局部 变量。
局部变量只能用于定义它函数内部。对于其他的函数或脚本代码是不可用的。
全局和局部变量即便名称相同它们也是两个不同的变量。修改其中一个不会影响另一个的值。 变量声明时如果不使用 var 关键字那么它就是一个全局变量即便它在函数内定义。 变量生命周期
全局变量的作用域是全局性的即在整个JavaScript程序中全局变量处处都在。
而在函数内部声明的变量只在函数内部起作用。这些变量是局部变量作用域是局部性的函数的参数也是局部性的只在函数内部起作用。
计数器困境
设想下如果你想统计一些数值且该计数器在所有函数中都是可用的。
你可以使用全局变量函数设置计数器递增
var counter 0;function add() {return counter 1;
}add();
add();
add();// 计数器现在为 3计数器数值在执行 add() 函数时发生变化。
但问题来了页面上的任何脚本都能改变计数器即便没有调用 add() 函数。
如果我在函数内声明计数器如果没有调用函数将无法修改计数器的值
function add() {var counter 0;return counter 1;
}add();
add();
add();// 本意是想输出 3, 但事与愿违输出的都是 1 !
以上代码将无法正确输出每次我调用 add() 函数计数器都会设置为 1。
JavaScript 内嵌函数可以解决该问题。
JavaScript 内嵌函数
所有函数都能访问全局变量。
实际上在 JavaScript 中所有函数都能访问它们上一层的作用域。
JavaScript 支持嵌套函数。嵌套函数可以访问上一层的函数变量。
该实例中内嵌函数 plus() 可以访问父函数的 counter 变量
function add() {var counter 0;function plus() {counter 1;}plus(); return counter;
}如果我们能在外部访问 plus() 函数这样就能解决计数器的困境。
我们同样需要确保 counter 0 只执行一次。
我们需要闭包。
JavaScript 闭包
还记得函数自我调用吗该函数会做什么
var add (function () {var counter 0;return function () {return counter 1;}
})();add();
add();
add();// 计数器为 3实例解析
变量 add 指定了函数自我调用的返回字值。
自我调用函数只执行一次。设置计数器为 0。并返回函数表达式。
add变量可以作为一个函数使用。非常棒的部分是它可以访问函数上一层作用域的计数器。
这个叫作 JavaScript 闭包。它使得函数拥有私有变量变成可能。
计数器受匿名函数的作用域保护只能通过 add 方法修改。 闭包是一种保护私有变量的机制在函数执行时形成私有的作用域保护里面的私有变量不受外界干扰。 直观的说就是形成一个不销毁的栈环境。