js学习-4(函数和作用域)
一、函数
函数: 将一些功能或语句进行封装,在需要的时候进行调用即可。
函数的作用:
1)将大量重复的语句利用函数进行封装,在需要的时候调用即可,避免了重复劳动。
2)将编程模块化,更加利于后期的维护。
函数的定义:
1、法一:使用函数声明来创建函数
function 函数名([形参1,形参2....形参N]){
语句....
}
比如:
function sum(a, b){
return a+b;
}
- function:是一个关键字。中文是“函数”、“功能”。
- 函数名字:命名规定和变量的命名规定一样。只能是字母、数字、下划线、美元符号,不能以数字开头。
- 参数:可选。
- 大括号里面,是这个函数的语句。
2、法二:使用函数表达式创建函数
var 函数名 = function([形参1,形参2...形参N]){
语句....
}
3、法三:使用构造函数创建一个对象(用的比较少)
函数的调用:
语法:函数名字()
函数的参数:
**形参:**形式参数,表示接收一个值。
可在函数中定义多个或一个。
多个形参之间使用,
隔开,声明形参就相当于在函数内部声明了对应的变量,但是并不赋值。
**实参:**实际参数,表述真实的数值、字符串。
调用函数时,实际传入的值。实参会将值赋给对应的形参。
sum(3,4); //这里的3,4就是实参
sum("3",4);
sum("Hello","World");
//函数:求和
function sum(a, b) {
console.log(a + b); //这里的a,b就是形参
}
实参的类型:
函数的实参可以是任意的数据类型。
调用函数时解析器不会检查实参的类型,所以要注意,是否有可能会接收到非法的参数,如果有可能则需要对参数进行类型的检查。
实参的数量:
注意:JavaScript里不会对函数实际传入的参数进行检测。可以传值,也可以不传值,也可以任意传多个值
调用函数时,解析器也不会检查实参的数量:
- 多余实参不会被赋值
- 如果实参的数量少于形参的数量,则没有对应实参的形参将是undefined。
auguments:获取所有的实际传递的参数
<script type="text/javascript">
function add(){
var sum=0;
console.log(arguments);
for (var i=0;i<arguments.length;i++) {
sum=sum+arguments[i];
}
return sum;
}
var sum = add(1,2,3,4,5,5);
console.log(sum);
</script>
函数的返回值:
利用return来返回最终的值,它也具有结束方法的作用。
注:
- return后的值将会作为函数的执行结果返回,可以定义一个变量,来接收该结果。
- 在函数中return后的语句都不会执行(函数在执行完 return 语句之后停止并立即退出)
- 如果return语句后不跟任何值,就相当于返回一个undefined
- 如果函数中不写return,则也会返回undefined
- 返回值可以是任意的数据类型,可以是对象,也可以是函数。
函数名、函数体、函数的加载问题【!!!重要】
函数名==整个函数
function f1(){
alert("emmmmm");
}
console.log(f == console.log(function f(){alert("emmmmm")});
当我们在调用一个函数时,通常使用函数()
这种格式;但此时,我们是直接使用函数
这种格式,它的作用相当于整个函数。
函数的加载问题:
js在加载的时候,只加载函数名,不加载函数体。所以如果想要使用内部的成员变量,需要调用函数。
f()和f的区别【重要!!!】
f():调用函数。相当于获取了函数的返回值。
f:函数对象。相当于直接获取了函数对象。
立即执行函数:
立即执行函数:函数被定义完,立即被调用,就称为立即执行函数。
立即执行函数往往只执行一次,因为没有变量保存它,执行完了,就没了,找不到了。
匿名函数:没有函数名的函数。
匿名函数:
function(a, b) {
console.log("a = " + a);
console.log("b = " + b);
};
立即执行函数:
(function(a, b) {
console.log("a = " + a);
console.log("b = " + b);
})(123, 456); //这里直接对形参赋值
另一种立即执行函数形式:
!function(a, b) {
console.log("a = " + a);
console.log("b = " + b);
}(123, 456);
方法:
当一个函数是作为一个对象的属性的时候,我们就称这个函数是对象的方法。
调用该函数就说是调用对象的方法。
(emmm,只是名称上改变了,用法并没有区别)
调用函数:fn();
调用方法:obj.fn();
二、作用域(面试时很重要)
2.1作用域:
指一个变量或者函数的作用范围。
在js中,作用域主要分为全局作用域和函数作用域。
2.1.1全局作用域:
直接编写在script标签中的JS代码,都在全局作用域。
特点:
1)全局作用域在页面打开时创建,在页面关闭时销毁。
2)在全局作用域中有一个全局对象window,他代表的是一个浏览器的窗口,它由浏览器创建我们可以直接使用。
3)在全局作用域中,创建的变量都会作为window对象的属性保存。
4)在全局作用域中,创建的函数都会作为window对象的方法保存。
5)全局作用域中的变量都是全局变量,在任意部分都可以访问。
2.1.2函数作用域:
变量声明在函数中,则其作用域为函数作用域。(必须加var,不加var的都是全局作用域)
执行期上下文:当函数执行时,会创建一个执行期上下文的内部对象。每调用一次函数,就会创建一个新的上下文对象,他们之间是相互独立的。当函数执行完毕,它所产生的执行期上下文会被销毁。
当函数内部的变量被另外一个函数所引用,那么这个函数的变量将不会在执行完毕后销毁。
函数作用域的上下级关系:
当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用(就近原则)。如果没有则向上一级作用域中寻找,直到找到全局作用域;如果全局作用域中依然没有找到,则会报错ReferenceError。
在函数中要访问全局变量可以使用window对象。(比如说,全局作用域和函数作用域都定义了变量a,如果想访问全局变量,可以使用window.a
)
特性:
1)使用var关键字声明的变量,会在函数中所有的代码执行之前被声明
2)函数声明也会在函数中所有的代码执行之前执行
3)在函数中,没有var声明的变量都是全局变量,而且并不会提前声明。
4)定义形参就相当于在函数作用域中声明了变量。
var a = 1;
function foo() {
console.log(a);
a = 2; // 此处的a相当于window.a(但是执行完也还是会被销毁的)
}
foo(); //输出结果为1
console.log(a); //输出结果是2
2.2声明提升(变量的声明提前、函数的声明提前)
2.2.1变量的声明提前:
使用var关键字声明的变量( 比如 var a = 1
),会在所有的代码执行之前被声明(但是不会赋值),但是如果声明变量时不是用var关键字(比如直接写a = 1
),则变量不会被声明提前。
console.log(a);
var a = 124; //输出结果为:underfined
console.log(a);
a = 123; //程序为报错:a is not defined
2.2.2函数的声明提前:
以函数声明的方式创建:
使用函数声明
的形式创建的函数function foo(){}
,会被声明提前。
也就是说,整个函数会在所有的代码执行之前就被创建完成,所以我们可以在函数声明之前,调用函数。
fn1(); // 虽然 函数 fn1 的定义是在后面,但是因为被提前声明了, 所以此处可以调用函数
function fn1() {
console.log('我是函数 fn1');
}
以函数表达式的方式创建:
使用函数表达式
创建的函数var fn = function(){}
,不会被声明提前,所以不能在声明前调用。
因为此时fn(作为变量)被声明了,且为undefined,并没有把 function(){}
赋值给 fn。
fn();
var fn = function(){console.log("函数表达式创建函数")}
本文地址:https://blog.csdn.net/qq_42760119/article/details/107374317