概述
子程序是一个大型程序中的某部分代码,有一个或多个语句块组成,它负责完成某项特定任务,而且相较于其他代码,具备有独立性,一般会有输入参数和返回值,提供对过程的封装和细节的隐藏;
在JS中子程序被称作函数,也就是function,如果函数挂挂载在一个对象上,就称它为对象的方法;
函数基础
使用关键字function定义,通常用2种方式:函数的声明语句和函数的表达式
//函数声明
function sum(a,b){return a+b};//sum是函数名,a,b是形参列表,return a+b这个大括号里面的是函数体
//函数表达式
var a=function sum(a,b){return a+b};
通常函数都会包含一个return,如果没有return,那么返回值就是undefined
函数定义:构造函数的形式
第三种定义的方式是使用function构造函数,最后一个参数是函数体,之前的都是函数的形参
var sum=new function{"num1","num2","return num1+num2"}
函数调用
function sum(a,b){return a+b}
var x=sum(1,1) //这边括号里的(1,1)是实参,和形参是一一对应的
console.log(x) //2
函数参数
function sum(a,b=1){return a+b}
var x=sum(1,1)
参数可以设定默认值,如果调用时没有传入对应的值,那么就会调用默认值,比如:
function sum(a,b = 1) {
return a+b;
}
var a=sum(1);
console.log(a); //a为2
函数内部属性
在函数内部,有两个特殊对象:arguments和this;
arguments:在函数体内,arguments表示实参列表对象,它是一个类数组,可以通过下标访问实参值,例如:
function sum() {
return arguments[0]+arguments[1];
}
console.log(sum(1,2))
this:在函数体内,this是指函数执行的环境对象(也叫context),一般来说,this是指调用函数的对象,如果没有,就是全局对象,在浏览器中就是window对象;
var a=function () {
console.log(this);
}
a(); //输出window对象
var obj={
a:function () {
console.log(this)
}
}
obj.a(); //输出obj
在js中,函数是一种特殊对象
函数是一种特殊的对象,意味着它也是一种值,所以函数可以当作参数传递,赋值变量,作为数组的元素等
function fa(a,b) {
return a(b)
}
function sum(d) {
return 1+d;
}
console.log(fa(sum,3));
函数是一种特殊的对象,那么也可以拥有属性和方法,函数有两个标准属性:length,name,方法有call,apply,bind
length:是该函数期望参数的个数,不包括默认值和剩余参数,长度只计算到第一个参数默认参数或剩余参数前的位置,例如
function xa(a,mun=1,...mun2) { }
function xb(a,mun=1,num3,...mun2) { }
console.log(xa.length) //1
console.log(xb.length) //1
函数的name属性是该函数的名称,示例:
function sum1(d) {return 1+d;}
var obj={
a:function () {}
}
var ac=new Function();
console.log(sum1.name); //sum1
console.log(obj.a.name); //a
console.log(ac.name); //anonymous
第三个比较特殊,是一个匿名函数,所以属性名的输出为anonymous
下面的代码解释call(),apply(),bind()示例中,解决的同一个问题是:
1.如果用this.name获取到joy这个值
2.函数say如何接收更多的参数
call方法:调用函数,可以指定函数中的this和传参列表
var obj={
name:"joy",
say:function (content) {
var say=function () {
console.log(this.name+' say '+content)
};
say();
}
};
obj.say("welcome");
上例中的打印this.name并没有打印出本对象中的name,因为如果没有指定的话this指的是全局的window的,window并没有name这个属性,所以没有显示,所以要做如下显示,将say(),这个启用,改成say.call(this),指定了对象是obj对象,当然这个写法等同于say.call(obj),但是这种写法如果对象名改变了就需要重写修改,不如this来的方便
var obj={
name:"joy",
say:function (content) {
var say=function () {
console.log(this.name+' say '+content)
};
say.call(this); //this改成obj也可以,但是可扩展性不高
}
};
obj.say("welcome");
如果想传入更多的参数那么可以改成obj.say("welcome","school","name"),然后将say:function(content,a,b)这边修改
apply方法:调用函数,可以指定函数中的this和传入参数数组,注意,apply和call的区别在于传参,call传的是参数列表,而apply传入的是数组
上例中,将
var obj={
name:"joy",
say:function (content,array) {
var say=function () {
console.log(this.name+' say '+content+array[0]+array[1])
};
say.apply(this);
}
};
obj.say("welcome",[" a "," b "]);
call()方法和apply()方法没有实质的区别,唯一的区别是call传入的是参数列表,apply传入的是数组(记忆小技巧,apply和array都是a开头的,记住apply是数组);
bind()方法:生成一个新的函数,可以指定函数调用时的this对象和传参列表
var obj={
name:"joy",
say:function (content,a,b) {
var say=function () {
console.log(this.name+' say '+content)
};
say();
}
};
obj.say("welcome");
bind()方法因为是生成了一个函数,因此,如下示例:
var obj={
name:"joy",
say:function (content,a,b) {
var say=function () {
console.log(this.name+' say '+content)
};
var say1=say.bind(this); //需要新建一个say1,
say1();
console.log(say==say1); //say和say1并不相等,说明不是一个函数
}
};
obj.say("welcome");
传参数的方式和call相等用逗号隔开的参数
变量作用域简介
JS查找变量的过程:先查找局部作用域,再查找嵌套作用域(不一定有),再查找全局作用域,个人理解:还是就近查找,如果没有就往上一层查,一层一层往上;
在JS中作用域分为:局部作用域和全局作用域,局部作用域中的变量叫做局部变量,全局作用域中的变量叫做全局变量
局部变量在每次执行函数的时候都会创建,执行结束后销毁,函数外不可访问;
全局变量在所有代码中都可以访问和修改;
另外:局部变量中的变量名可以和全局变量中的相同,但是两者没有关系
在es6中引入了let,const,它们是声明块级作用域变量,块由{}组成
obj.say("welcome");
let x=10;
var y=10;
{
let x=5;
var y=5;
{
let x=2;
var y=2;
console.log(x+" "+y) //2 2
}
console.log(x+" "+y); //5 2
}
console.log(x+" "+y); //10 2
这边的let因为是块级变量,所以相互不守干扰,但是y就不行,受到了最里层的定义影响
原型简介
对象除了自身的属性外,还可以从一个称为原型(prototype)的对象继承属性。原型式继承是JS的核心特征。
箭头函数
箭头函数表达式的语法比函数更加简短,并且不能绑定自己的this,arguments,super和new.target。这些函数表达式最合适
用于非方法函数,并且它们不能用作构造函数,如下示例:
var a=["qasdd","wasdd","asde","easd","r1ee"];
var x=a.map(function (a) {
return a.length
});
console.log(x) //5 5 4 4 4
var m=a.map((a) => {
return a.length
});
console.log(m); //5 5 4 4 4
var n=a.map(x=>x.length)
console.log(n); //5 5 4 4 4