JavaScript 使用关键字 function 定义函数
函数可以通过声明定义,也可以是一个表达式
函数声明
函数声明的语法 :
函数声明后不会立即执行,会在我们需要的时候调用到
分号是用来分隔可执行JavaScript语句,由于函数声明不是一个可执行语句所以不以分号结束
JavaScript 函数可以通过一个表达式定义
函数表达式可以存储在变量中:
在函数表达式存储在变量后,变量也可作为一个函数使用:
两者的区别:解析器会先读取函数声明,并使其在执行任何代码之前可以访问;而函数表达式则必须等到解析器执行到它所在的代码行才会真正被解释执行。
以上函数实际上是一个 匿名函数 (函数没有名称)。函数存储在变量中,不需要函数名称,通常通过变量名来调用。上述函数以分号结尾,因为它是一个执行语句。
1 常见写法:
2 匿名函数
3 自调用函数:
4 函数嵌套
5 函数继承和构造函数
Function() 构造函数
在以上实例中,我们了解到函数通过关键字 function 定义。函数同样可以通过内置的 JavaScript 函数构造器(Function())定义
实际上,你不必使用构造函数。上面实例可以写成:
在 JavaScript 中,很多时候,你需要避免使用 new 关键字
函数提升(Hoisting)
提升(Hoisting)是 JavaScript 默认将当前作用域提升到前面去的的行为。
提升(Hoisting)应用在变量的声明与函数的声明,因此,函数可以在声明之前调用:
使用表达式定义函数时无法提升
以上代码运行即会报错,原因在于函数位于一个初始化语句中,而不是一个函数声明。换句话讲,在执行到函数所在的语句之前,变量myFunction中不会保存有对函数的引用;而且,由于第一行代码就会导致“unexpected identifier”(意外标识符)错误,实际上也不会执行到下一行。
除了声明时候可以通过变量访问函数这一点区别之外,函数声明与函数表达式的语法其实是等价的。
自调用函数
函数表达式可以 "自调用"。自调用表达式会自动调用。如果表达式后面紧跟 () ,则会自动调用。不能自调用声明的函数。通过添加括号,来说明它是一个函数表达式:
以上函数实际上是一个 匿名自我调用的函数
自调用函数可用来传参带返回值
自执行函数严格来说也叫函数表达式,它主要用于创建一个新的作用域,在此作用域内声明的变量,不会和其它作用域内的变量冲突或混淆,大多是以匿名函数方式存在,且立即自动执行。
JavaScript函数可作为一个值使用
JavaScript函数可作为表达式使用:
函数是对象
在 JavaScript 中使用 typeof 操作符判断函数类型将返回 "function" ,但JavaScript 函数描述为一个对象更加准确。
JavaScript 函数有属性和方法。
arguments.length 属性返回函数调用过程接收到的参数个数:
toString() 方法将函数作为一个字符串返回:
函数定义作为对象的属性,称之为对象方法。
函数如果用于创建新的对象,称之为对象的构造函数
JavaScript 函数参数
JavaScript 函数对参数的值(arguments)没有进行任何的检查
函数显式参数与隐藏参数(arguments)
函数显式参数在函数定义时列出
函数隐藏参数(arguments)在函数调用时传递给函数真正的值
参数规则
JavaScript 函数定义时参数没有指定数据类型,对隐藏参数(arguments)没有进行检测,对隐藏参数(arguments)的个数没有进行检测
默认参数
如果函数在调用时缺少参数,参数会默认设置为: undefined
有时这是可以接受的,但是建议最好为参数设置一个默认值:
或者,更简单的方式:
如果y已经定义, y || 返回y, 因为y是 true, 否则返回 0, 因为undefined为 false
如果函数调用时设置了过多的参数,参数将无法被引用,因为无法找到对应的参数名。 只能使用 arguments 对象来调用
Arguments 对象
JavaScript 函数有个内置的对象 arguments 对象。arguments 对象包含了函数调用的参数数组。通过这种方式你可以很方便的找到每个参数的值:
或者创建一个函数用来统计所有数值的和:
通过值传递参数
在函数中调用的参数是函数的参数。
如果函数修改参数的值,将不会修改参数的初始值(在函数外定义)。
通过对象传递参数
在JavaScript中可以引用对象的值,因此我们在函数内部修改对象的属性就会修改其初始的值。
修改对象属性可作用于函数外部(全局变量)。
JavaScript 函数调用
JavaScript 函数有 4 种调用方式。每种方式的不同方式在于 this 的初始化
this 关键字
一般而言,在Javascript中,this指向函数执行时的当前对象
注意 this 是保留关键字,你不能修改 this 的值
调用 JavaScript 函数
函数中的代码在函数被调用后执行
作为一个函数调用
以上函数不属于任何对象。但是在 JavaScript 中它始终是默认的全局对象。
在 HTML 中默认的全局对象是 HTML 页面本身,所以函数是属于 HTML 页面。
在浏览器中的页面对象是浏览器窗口(window 对象)。以上函数会自动变为 window 对象的函数
myFunction() 和 window.myFunction() 是一样的:
这是调用 JavaScript 函数常用的方法, 但不是良好的编程习惯。全局变量,方法或函数容易造成命名冲突的bug
全局对象
当函数没有被自身的对象调用时, this 的值就会变成全局对象。
在 web 浏览器中全局对象是浏览器窗口(window 对象)。
该实例返回 this 的值是 window 对象:
函数作为全局对象调用,会使 this 的值成为全局对象。使用 window 对象作为一个变量容易造成程序崩溃
函数作为方法调用
在 JavaScript 中你可以将函数定义为对象的方法。
以下实例创建了一个对象 (myObject), 对象有两个属性 (firstName 和 lastName), 及一个方法 (fullName):
ullName 方法是一个函数。函数属于对象。 myObject 是函数的所有者。
this对象,拥有 JavaScript 代码。实例中 this 的值为 myObject 对象。
测试以下!修改 fullName 方法并返回 this 值:
函数作为对象方法调用,会使得 this 的值成为对象myObject本身
使用构造函数调用函数,参数必须加引号
如果函数调用前使用了 new 关键字, 则是调用了构造函数。这看起来就像创建了新的函数,但实际上 JavaScript 函数是重新创建的对象:
构造函数的调用会创建一个新的对象。新对象会继承构造函数的属性和方法
构造函数中 this 关键字没有任何的值。this 的值在函数调用时实例化对象(new object)时创建。
作为函数方法调用函数
在 JavaScript 中, 函数是对象。JavaScript 函数有它的属性和方法。call() 和 apply() 是预定义的函数方法。 两个方法可用于调用函数,两个方法的第一个参数必须是对象本身。
两个方法都使用了对象本身作为第一个参数。 两者的区别在于第二个参数: apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)。call和apply的第一个参数就是this指针要指向的对象
在 JavaScript 严格模式(strict mode)下, 在调用函数时第一个参数会成为 this 的值, 即使该参数不是一个对象。
在 JavaScript 非严格模式(non-strict mode)下, 如果第一个参数的值是 null 或 undefined, 它将使用全局对象替代。
通过 call() 或 apply() 方法你可以设置 this 的值, 且作为已存在对象的新方法调用
JavaScript 闭包
JavaScript 变量可以是局部变量或全局变量
私有变量可以用到闭包
局部变量和全局变量
函数可以访问函数内部定义的变量
函数也可以访问函数外部定义的变量
后面一个实例中, a 是一个全局变量。在web页面中全局变量属于 window 对象。全局变量可应用于页面上的所有脚本。
在第一个实例中, a是一个局部变量。局部变量只能用于定义它函数内部。对于其他的函数或脚本代码是不可用的。全局和局部变量即便名称相同,它们也是两个不同的变量。修改其中一个,不会影响另一个的值。
变量声明是如果不使用 var 关键字,那么它就是一个全局变量,即便它在函数内定义
变量生命周期
全局变量的作用域是全局性的,即在整个JavaScript程序中,全局变量处处都在。而在函数内部声明的变量,只在函数内部起作用。这些变量是局部变量,作用域是局部性的;函数的参数也是局部性的,只在函数内部起作用。
计数器困境
设想下如果你想统计一些数值,且该计数器在所有函数中都是可用的。你可以使用全局变量,函数设置计数器递增:
计数器数值在执行 add() 函数时发生变化。但问题来了,页面上的任何脚本都能改变计数器,即便没有调用 add() 函数。如果我在函数内声明计数器,如果没有调用函数将无法修改计数器的值:
以上代码将无法正确输出,每次我调用 add() 函数,计数器都会设置为 1。JavaScript 内嵌函数可以解决该问题
JavaScript 内嵌函数
所有函数都能访问全局变量。 实际上,在 JavaScript 中,所有函数都能访问它们上一层的作用域。JavaScript 支持嵌套函数。嵌套函数可以访问上一层的函数变量。
该实例中,内嵌函数 plus() 可以访问父函数的 counter 变量:
如果我们能在外部访问 plus() 函数,这样就能解决计数器的困境。我们同样需要确保 counter=0 只执行一次。我们需要闭包。
JavaScript 闭包
变量 add 指定了函数自我调用的返回字值。自我调用函数只执行一次。设置计数器为 0。并返回函数表达式。add变量可以作为一个函数使用。非常棒的部分是它可以访问函数上一层作用域的计数器。这个叫作 JavaScript 闭包。它使得函数拥有私有变量变成可能。计数器受匿名函数的作用域保护,只能通过 add 方法修改。
闭包是可访问上一层函数作用域里变量的函数,即便上一层函数已经关闭
欢迎加油QQ群461593224 web前端 学习交流
数(Function)是被设计为执行特定任务的代码块。它在可以实现定制运算功能的同时,还带有一个入口和一个出口。所谓的入口,就是函数所带的各个参数,我们可以通过这个入口,把函数的参数值代入子程序,供计算机处理;所谓出口,就是指函数的函数值,在计算求得结果之后,由此口带回给调用它的程序。
在程序设计中,常将一些常用的功能模块编写成函数,放在函数库中供用户选用。善于利用函数,可以减少重复编写程序段的工作量。
本文介绍Javascript函数的几种常用定义方式。掌握JS函数基本技术后,在统计数据处理过程中,我们将函数理解为某一统计对象(项目)所定制的方法。
导读:
1、普通函数
I、基本语法
function 函数名称(参数1, 参数2, 参数3) {
//要执行的代码
return 返回值
}
JavaScript函数语法解析如下:
II、无参数函数
console.clear();
function test1() {
return "Hello World!";
}
//执行函数返回"Hello World!",并赋值给变量str
var str=test1();
console.log(str);
注:Console对象用于JavaScript调试,为了显示Console.log输出结果,通过按Control+Shift+i(PC平台)来打开Console窗口
III、有参数函数
//计算任意两个数的和
function oSum(x, y) {
return x+y;
}
var mySum=oSum(15, 85);
console.log(mySum); //100
IV、参数默认值设置
//求和函数中给两个参数设置默认值
console.clear();
function oSum(x=50, y=50) {
return x+y;
}
var mySum=oSum(15, 55);
console.log(mySum); //70
mySum=oSum(15);
console.log(mySum); //65
mySum=oSum();
console.log(mySum); //100
V、参数为函数
console.clear();
function oSum(x, y) {return x+y;}
var mySum=oSum(oSum(45, 75), 100);
console.log(mySum); //220
VI、对象{}为参数 - 解构赋值默认值
console.clear();
function oSum({x=10, y=20}) {
return x+y;
}
console.log(oSum({})); //30,这里直接调用oSum()出错
console.log(oSum({x:100})); //120
console.log(oSum({y:100})); //110
console.log(oSum({x:100,y:200})); //300
console.log(oSum({y:50,x:20})); //70
VII、对象{}为参数 - 双重默认值
//代码容错更好
console.clear();
function oSum({x=10, y=20}={}) {
return x+y;
}
console.log(oSum()); //30
console.log(oSum({})); //30
console.log(oSum({x:100})); //120
console.log(oSum({y:100})); //110
console.log(oSum({x:100,y:200})); //300
console.log(oSum({y:50,x:20})); //70
2、函数arguments对象
在JavaScript中,参数在函数内部是以一个数组表示的,arguments是函数内部的一个专门用来存储实参的数组对象。函数arguments的对象在函数运行时用于检测和重新设置参数。
I、arguments.length - 函数参数数量
console.clear();
function fn(a,b,c){
console.log(arguments.length); //3
return a+b+c;
}
console.log(fn(1,2,3)); //6
II、arguments[] - 函数输出和设置
console.clear();
function fn(a,b,c){
console.log(arguments[0]); //1
console.log(arguments[1]); //2
console.log(arguments[2]); //3
arguments[0]=5; //重新设置参数a=5
return a+b+c;
}
console.log(fn(1,2,3)); //10
III、arguments转数组
arguments对象不是一个真正的数组 ,它类似于数组,但除了length属性和索引元素之外没有任何数组属性。例如,它没有pop方法。但是它可以被转换为一个真正的数组,转换为真实的数组后就可以使用完整的数组方法
console.clear();
function fn(a, b, c) {
var arr=Array.from(arguments); //进行转数组操作
console.log(arr); //输出数组
return a + b + c;
}
console.log(fn(1, 2, 3)); //6
3、匿名函数
匿名函数顾名思义指的是没有名称的函数,在实际开发中使用的频率非常高,是学好JS编程的重点。
I、变量匿名函数
console.clear();
var fn=function fn(a,b,c=9) {
return a+b+c;
}
console.log(fn(1,2)); //12
console.log(fn(1,2,3)); //6
II、无名称匿名函数
即在函数声明时,在后面紧跟参数。JS语法解析此函数时,里面代码立即执行。
console.clear();
console.log(function(a,b){return a+b;}(2,3));
console.clear();
//加括号执行无匿名函数(输出"Hello Word!")
(function (){
console.log("Hello Word!");
})()
//加括号执行有匿名函数(输出"Hello Word! lei.")
(function (str){
console.log("Hello Word!" +" "+ str +".");
})("lei")
注:函数代码function(a,b){return a+b;}没指定函数名称,如果需要执行匿名函数,在匿名函数后面加上一个括号即可立即执行
III、事件绑定匿名函数
通常我们浏览网页时会通过鼠标或键盘输入信息,例如鼠标点击某个按钮称“click点击事件”、文本框内文字信息改变了称“change事件”。总之,用户所有的鼠标、键盘操作都称为事件,都可以通过JS代码来捕获这些事件。
console.clear();
//通过id或取图标对象
var logo=document.querySelector("#myLogo");
//给左上角“银河统计”图标增加点击事件
logo.onclick=function(){
console.log("欢迎来到银河统计工作室!");
}
logo.onmousemove=function(){
logo.style.cursor="pointer";
console.log("鼠标在图像上面!");
}
logo.onmouseout=function(){
logo.style.cursor="default";
console.log("鼠标已经离开图像!");
}
注:代码中网页图像标记为<img id="myLogo" src="###"/>
IV、对象绑定匿名函数做为对象的方法
前面我们介绍JS对象时提到,事件是有属性和方法组成的数据结构,事件的方法可以通过绑定匿名函数的方式建立。
console.clear();
var obj={
name:"Carolyn",
age:11,
fn:function(str){
return "My name is "+this.name+" Siyu"+". I'm "+this.age+" years old now.";
}
};
console.log(obj.fn("Siyu")); //My name is Carolyn Siyu. I'm 11 years old now.
注:这里定匿名函数为属性的返回值
V、匿名函数做为回调函数(callback)
什么是同步,什么是异步?
同步指的是一次只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推。
异步指的是每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。
JS是单线程的,它本身不可能是异步的,通过回调函数可以实现异步。JS中最基础的异步是setTimeout和setInterval函数。
console.clear();
var interval=setInterval(function(){
console.log("回调函数,每间隔1秒钟会被执行一次");
},1000);
//点击银河统计图表停止setInterval计算器运行
var logo=document.querySelector("#myLogo");
logo.onclick=function(){
console.log("Stop!");
clearInterval(interval)
}
setTimeout(function() {
console.log("张三")
}, 1000 );
setTimeout(function() {
console.log("李四")
}, 2000 );
setTimeout(function() {
console.log("王五")
}, 3000 );
//jS最基础的异步实现
function a() {
console.log("执行a函数");
setTimeout(function() {
console.log("执行a函数的延迟函数");
},2000);
}
function b() {
console.log("执行b函数");
}
a();
b();
VI、匿名函数做为返回值
console.clear();
function fn(){
return function(){
return "Carolin";
}
}
//调用匿名函数
console.log(fn()()); //Carolin
//或者
var box=fn();
console.log(box()); //Carolin
4、闭包和递归函数
假设,函数A内部声明了个函数B,函数B引用了函数B之外的变量,并且函数A的返回值为函数B的引用,那么函数B就是闭包函数。
递归就是函数自己调用自己,当函数自己时,其自身为闭包函数,参数为域外变量。
console.clear();
function funA(arg1,arg2) {
var i=0; //funA作用域的变量
function funB(step) {
i=i + step; //访问funB作用域外变量i
console.log(i)
}
return funB;
}
var allShowA=funA(2, 3); //调用的是funA arg1=2,arg2=3
allShowA(1);//调用的是funB step=1,输出 1
allShowA(3);//调用的是funB setp=3,输出 4
//累加
console.clear();
function f(num){
if(num<1) {
return 0;
} else {
return f(num-1)+num;
}
}
console.log(f(9)); //45
//阶乘
console.clear();
function f(num){
if(num<1) {
return 1;
} else {
return f(num-1)*num;
}
}
console.log(f(4)); //24
//在对象中定义递归方法
var obj={
num : 5,
fac : function (x) {
if (x===1) {
return 1;
} else {
return x * obj.fac(x - 1);
}
}
};
console.log(obj.fac(5)) /120
//使用arguments.callee
function fact(num){
if (num<=1){
return 1;
}else{
return num*arguments.callee(num-1);
}
}
console.log(fact(4)); //24
5、Promise回调函数
Promise是ES6语言标准中提供的对象。Promise是异步编程的一种解决方案,比传统的解决方案(回调函数和事件)更合理和更强大。
console.clear();
//基本用法,
var p=new Promise(function(resolve, reject){
setTimeout(function(){
resolve(console.log("done"));
}, 1000);
});
//做为对象返回
function timeout(ms) {
return new Promise((resolve, reject)=> {
setTimeout(resolve, ms, 'done');
});
}
timeout(1000).then((value)=> { //参数value='done'
console.log(value);
});
//完整使用方法
function promiseTest(){
let p=new Promise(function(resolve, reject){
setTimeout(function(){
var num=Math.random()*100; //生成1-100的随机数
console.log('随机数生成的值:',num)
if(num>=60){
resolve(num);
} else {
reject('数字太于60了即将执行失败回调');
}
}, 2000);
})
return p
}
promiseTest().then(
function(data){ //data=num
console.log('resolved成功回调');
console.log('成功回调接受的值:',data);
}
)
.catch(function(reason, data){
console.log('catch到rejected失败回调');
console.log('catch失败执行回调抛出失败原因:',reason);
});
注:Promise回调函数在网页数据抓取时常常遇到
JavaScript是一种面向对象的编程语言,因此对象在JavaScript中扮演了很重要的角色。
Javascript函数是能完成某个常用功能的一小段代码,而Javascript方法(method)是通过对象调用的Javascript函数。
JS中所有事物都是对象,对象是拥有属性和方法的数据。但是,JS对象又是由函数创建的,JS函数本身也是对象。“方法是函数、对象是函数”,JS中函数的用途和含义有点绕口,需要大量练习和运用才能掌握。
数的定义方式
1. 函数声明方式 function 关键字 (命名函数)
2. 函数表达式 (匿名函数)
3. new Function()
Function 里面参数都必须是字符串格式
第三种方式执行效率低,也不方便书写,因此较少使用
所有函数都是 Function 的实例(对象)
函数也属于对象
函数的调用方式
1. 普通函数
function fn() {
console.log('人生的巅峰');
}
fn(); fn.call()
2. 对象的方法
var o={
sayHi: function() {
console.log('人生的巅峰');
}
}
o.sayHi();
3. 构造函数
function Star() {};
new Star();(构造函数和普通函数肯定不一样了,他们的主要区别是构造函数首字母大写,还有就是new关键字调用)
4. 绑定事件函数
btn.onclick=function() {}; // 点击了按钮就可以调用这个函数
5. 定时器函数
setInterval(function() {}, 1000); 这个函数是定时器自动1秒钟调用一次
6. 立即执行函数
(function() {
console.log('人生的巅峰');
})();
立即执行函数是自动调用
*请认真填写需求信息,我们会在24小时内与您取得联系。