不用去纠结为什么会是这样,这都是ES规定的,咱们只要弄懂这套规定就行。
函数function
函数也是对象,具有普通对象的所有功能,但比普通对象更强大。函数中可以封装一些功能(代码),需要的时候再执行这个功能(代码),提高了代码的可维护性。
如何使用函数
var fn1 = Function();
var fn2 = function(){
console.log("我是fn2里面的内容");
};
function fn3() {
console.log("我是fn3里面的内容!");
}
console.log(typeof fn1 , typeof fn2() ,typeof fn3);
结果
创建函数
- 通过构造函数
可以不传参,也可以传递引号引起来的JS语句。
很少使用构造函数这种方式 - 通过 function 关键字
语法:
function 函数名([参数1,参数2……参数n]){
……
}
//[]表示可选项
- 通过函数表达式
var 函数名 = function ([参数1,参数2……参数n]){
……
}
//[]表示可选项
- 匿名函数
function ([参数1,参数2……参数n]){
……
}
//[]表示可选项
使用函数
- 函数对象()
当调用函数时,函数里边封装的代码会被顺序执行。
我们声明函数时,将函数对象赋值给了一个变量(函数名),所以,我们一般通过变量名()
来调用。
但要牢记,原理是 :函数对象()
使用 typeof 运算符返回的是“function”,但是,代码中为何fn2()会是undefined呢?以后详解
函数的参数
需求:定义一个对两个数求和的函数,这两个数是由我们动态输入的,要求函数可以动态给出和。
实现这个需求需要用到函数的形参,形参就相当于在函数内部声明了变量并默认不赋值(值为undefined)。
function sum (num1, num2){
console.log(num1 + num2 + "为这两个数的和。");
}
sum(12,23);
图片.png
形参
num1和num2,默认值是undefined
实参
12和23
函数的实参可以是任意数据类型
调用函数时,浏览器不会检查实参的类型;所以,需要注意是否会收到非法的参数,如果有可能,则需要对参数进行类型的检查。
调用函数时,浏览器也不会检查实参的数量:多余的实参不会被赋值;没有实参对应的形参保持为默认值undefined
函数的返回值
我们的函数可以有输入——通过参数得方式;函数当然也可以有输出——通过return语句返回你想返回的。
我们可以定义变量接收这个返回结果再进行别的运算,也可以直接在语句中使用它。
return语句后面的语句都不会执行。
比如,我们的sum函数,可以改为:
function sum (num1, num2){
return (num1 + num2);
}
console.log(sum(12,23) + "为这两个数的和。");
一样被正确执行
刚开始时提到过,输出typeof fn2()的结果是undefined,原因如下:
typeof fn2()是一个表达式,()的优先级高于tyopeof,故会先执行fn2(),函数执行完后没有return语句按默认返回undefined,表达式变成typeof undefined,结果自然是undefined。
返回值的类型
返回值可以是任何类型。
函数练习
- 定义一个函数,判断数字是否是偶数
首先,是否是偶数可以通过%运算符,%运算符会将不是Number类型的操作数转为Number类型再运算。我们来回忆一下
转换为Number类型的几种情况:
纯数字的字符串转为对应数字
非纯数字的字符串转为NaN
空串或者全是空格的字符串,转换为0
true转为 1,false 转为 0
null转为0,undefined:转为NaN
再来回忆一下 %运算符的运算规则:
对于不是Number类型的运算数,会先转换为Number。
一般的数字就执行常规的除法运算,一些特殊数字返回特殊结果。
如果被除数是 Infinity,或除数是 0,结果为 NaN。
Infinity 被 Infinity 除,结果为 NaN。
如果除数是无穷大的数,结果为被除数。
如果被除数为 0,结果为 0
回忆完毕,回到函数上。
其次,输入的可能不是String类型的数字,是否需要转为Number类型呢?——不需要,%会转为Number类型再运算的。
再是,输入空字符串,全是空格的字符串 或者 null ,转为数字后为0,%2运算会返回0,如何避免
function isOu ( num ) {
if (num && num % 2 === 0){
// && 运算符的运算规则是 真后假前
return `${num} 是一个 偶数`;
} else {
return `${num} 不是一个 偶数`;
}
}
console.log(isOu("12"));
console.log(isOu(12));
console.log(isOu(11));
console.log(isOu(NaN));
console.log(isOu(" "));
console.log(isOu(""));
console.log(isOu(null));
console.log(isOu(undefined));
console.log(isOu({}));
基本都已经正确判断了,除了全是空格的字符串判为偶数
全是空格的字符串判为偶数该如何避免,
-
定义一个函数,可以根据一个圆的半径求出圆的面积并返回。
-
定义一个函数,输出人的信息:name,age,gender,address。其中,age默认为5,gender默认为女
function people ({name,age = 5,gender = "女", address}) {
return `我叫${name},今年${age}岁了 ,我是个${gender}生,家住在${address},欢迎常来找我玩!`
}
var people1 = {
name : "小花",
address: "西安"
};
var people2 = {
name : "小明",
address: "济南",
gender: "男",
age: 10
};
console.log(people(people1));
console.log(people(people2));
函数的实参,形参,返回值可以是任意类型,形参可以赋初始值
函数的实参,形参,返回值可以是任意数据类型,形参可以赋初始值
开发中,常用一个匿名函数作为实参传给另一个函数。
对于参数是对象,还有另外一种写法
var people2 = {
name : "小明",
address: "济南",
gender: "男",
age: 10
};
function people(obj){
console.log(`我叫${obj.name},今年${obj.age}岁了 ,我是个${obj.gender}生,家住在${obj.address},欢迎常来找我玩!`);
}
people(people2);
这样写的话,缺点就是不能赋初始值了
立即执行函数
函数中有一种函数叫做匿名函数。
如果,我们有一个需求是,这个函数只需要执行一次,以后都不会用了,我们就不需要创建一个函数名去保存它了!
是不是一定得有个函数名才行呢?——不是的
通过()表示这是一个函数对象
那怎么调用这种函数呢?
调用函数的语法:函数对象();
以前我们是声明了一个变量,将函数对象赋值给变量,最后通过
变量名()
来调用,而实际上是函数对象()
。现在,我们通过()表示这是一个函数对象的话,直接在()后边再加上()来调用就可以了!
(function(){
console.log("自执行函数!");
})();
函数被执行了
这种形式的函数叫做
立即执行函数
:即函数定义完立即被调用。这种函数一般只执行一次
,因为我们没有声明一个变量去长久地保存它!立即执行函数也
可以传参
的。
方法Method
如果某函数是某对象属性的属性值,那么就说这个函数属于这个对象,是这个对象的方法;调用函数就可以说成是调用该对象的方法。
在JS中,我们在script标签里面最外层声明
的所有东西都是属于window对象
。
我们前边写的console.log(),alert()等函数也是window对象提供的方法,调用window对象的属性或方法可以省掉 window. 以后详解window对象。
我们的变量名就是window对象的属性名
,我们的变量值就是window对象对应属性的属性值
我们的函数名作为window对象的属性名
,我们的函数对象作为window对象的对应属性的属性值
。
所以,我们之前在script标签里面最外层声明的那些函数,也可以看作是window对象的方法。
function fn1 () {
console.log("是fn1函数啦!");
}
var people = {};
people.age = 16;
people.sayAge = function () {
console.log("我的年龄是:" + this.age);
};
fn1();
people.sayAge();
window.fn1();
console.log(window);
可以看到:
window对象中有我们声明的fn1函数和people对象
people对象里边又有我们声明的age和sayName函数
访问对象里的属性和方法
讲对象的时候,提到过JS里边除了自定义的对象之外还有内建对象(Math,Number……)和宿主对象(window……),我们要会用这些对象。这些对象都是已经封装好的,我们怎么查看这些对象都有哪些属性跟方法呢?——
for……in的语法
for(var value in obj){
}
对象有几个属性,循环体就循环几次,每次循环时,会将对象中的一个属性名赋值给变量value
以window为例,输出所有的属性和属性值
for(var value in window){
console.log("属性名", value, "属性值", window[value]);
//注意获取值不要写成 window.value ,这样写的话则变成了找value属性的属性值
}
window对象
网友评论