目录
往期内容
四、函数
4.1 定义函数
- JavaScript 使用关键字 function 定义函数。
- 函数可以通过声明定义,也可以是一个表达式
1.声明定义
- 函数声明后不会立即执行,会在我们需要的时候调用到。
function 函数名(参数) {
执行的代码
}
定义一个绝对值函数
//定义函数 方式一
//绝对值函数
function abs(x){
if(x>=0){
return x;
}else{
return -x;
}
}
一旦执行到 return 代表函数结束,返回执行结果
如果没有执行 return , 函数执行完也会返回结果 undefined
2.表达式定义
- JavaScript 函数可以通过一个表达式定义
- 函数表达式可以存储在变量中
- 函数存储在变量中,不需要函数名称,通常通过变量名来调用
//定义方式二 与方式一等价
var abs=function (x){
if(x>=0){
return x;
}else{
return -x;
}
}
function(x){...} 是一个匿名函数,但可以把结果赋值给abs,通过abs就可以调用函数
4.2 参数问题
JavaScript 可以传任意个参数,也可以不传递参数
参数是否存在的问题? 假设不存在参数,如何规避?
1.手动抛出异常进行判断
function abs(x){
if(typeof x!=='number'){
//手动抛出异常来判断
throw 'not a number';
}
if(x>=0){
return x;
}else{
return -x;
}
}
2.arguments
arguments 是一个JS免费赠送的关键字
在函数体内可以通过arguments 对象来访问参数数组,从而获取传递给函数的每一个参数
var abs=function (x){
console.log("x=>"+x);
for(var i =0;i<arguments.length;i++){
console.log(arguments[i]);
}
if(x>=0){
return x;
}else{
return -x;
}
}
arguments包含所有的参数,我们有时候想使用多余的参数来进行附加操作,需要排除已有的参数
3.rest
-
ES6 引入的新特性,获取除了已经定义的参数之外的所有参数
-
rest就是为解决传入的参数数量不一定
-
rest parameter(rest 参数) 本身就是数组,数组的相关的方法都可以用
//以前判断多余的参数
function aaa(a,b){
console.log("a=>"+a);
console.log("b=>"+b);
if(arguments.length>2){
for(var i=2;i<arguments.length;i++){
}
}
}
rest 参数必须写在最后面,必须用...标识
function aaa(a,b,...rest){
console.log("a=>"+a);
console.log("b=>"+b);
console.log(rest);
}
4.3 变量的作用域
1.在函数体中声明,则在函数体外不可以使用
JavaScript中 var 定义变量实际是有作用域的
假设在函数体中声明,则在函数体外不可以使用( 如果非要实现的话 研究闭包)
function ax(){
var x=1;
x=x+1;
}
x=x+2;
对于上面的代码段,函数体内定义变量x,在函数体外使用
浏览器控制台会报错 Uncaught ReferenceError: x is not defined
2.如果两个函数使用了相同的变量名,只要在函数内部就不冲突
function ax(){
var x=1;
x=x+1;
return x;
}
function ax2(){
var x='a';
x=x+1;
return x;
}
3.内部函数可以访问外部函数的成员,反之则不行
function ax(){
var x=1;
function ax2(){
var y=x+1;
}
var z=y+1;
}
4.内部函数变量与外部函数变量重名
- 在JavaScript中函数查找变量从自身函数开始,由内向外查找
- 假设外部存在同名的函数变量,则内部函数会屏蔽外部函数的变量
function ax(){
var x=1;
function ax2(){
var x='A';
console.log('inner=>'+x)
}
console.log('outer=>'+x)
ax2()
}
5.提升变量作用域
function ax(){
var x="x "+y;
console.log(x);
var y='Y';
}
执行上面的代码段ax(),浏览器控制台输出x undefined
说明JS执行引擎自动提升了y声明,但是不会提升变量y的赋值
//等价于这种定义
function ax(){
var y;
var x="x "+y;
console.log(x);
}
这是在JS建立之初就存在的特性,养成规范:所有的变量定义都放在函数头部,便于代码维护
6.全局变量
- 使用 var(关键字)+ 变量名(标识符) 的方式
- 在 function 外部声明即为全局变量,否则在function声明的是局部变量
var x=123;
function f(){
console.log(x);
}
f();
console.log(x);
7.全局对象window
默认所有的全局变量,都会自动绑定在window对象
var x='xxx';
alert(x);
alert('window:'+window.x); //默认所有的全局变量,都会自动绑定在window对象
执行上面的代码段浏览器会弹窗两次
alert()这个函数本身也是window变量
var x='xxx';
window.alert(x);
var old_alert =window.alert;
old_alert(x);
//手动定义一个全局变量覆盖window.alert()
window.alert = function (){
}
window.alert(123) //会发现alert()失效
//要恢复,把定义的变量赋值回window.alert()
window.alert=old_alert;
window.alert(456);
说明 JavaScript 实际上只有一个全局作用域,任何变量(函数也可视为变量)
假设没有在函数作用范围内找到,就会向外查找
如果在全局作用域都没有找到,报错RefrenceError
window.alert(Q); //Q是不存在的变量
规范:
由于所有的全局变量都会绑定到window上,如果不同的js文件使用了相同的全局变量,产生冲突-->如何减少冲突?
把自己的代码全部放入自己定义的唯一空间名字中,来减少全局命名冲突的问题
//唯一全局变量
var HA={};
//定义全局变量
HA.name='Zhangsan';
HA.add=function (a,b){
return a+b;
}
//把自己的代码全部放入自己定义的唯一空间名字中,来减少全局命名冲突的问题
8.局部作用域
function aaa(){
for(var i=0;i<3;i++){
console.log(i);
}
console.log(i+1); //问题 i出了这个作用域还可以使用
}
出现问题 i出了这个作用域还可以使用
ES6 let 关键字 解决局部作用域冲突问题
function aaa(){
for(let i=0;i<3;i++){
console.log(i);
}
console.log(i+1); //报错
}
改成 let 定义后,在作用域外部使用就会报错,建议使用 let 定义局部作用域的变量
9.常量
在ES6之前,全部大写字母命名的变量就是常量,建议不要修改这样的值
var PI='3.14';
console.log(PI);
PI='4.31' //可以改变
console.log(PI)
在ES6引入了常量关键字 const
const PI='3.14';
console.log(PI);
PI='4.31' //只读变量
console.log(PI);
const 定义的变量不能被修改
4.4 方法
1.定义方法
-
方法就是把函数放在对象里面,对象:属性和方法
-
方法一定带 ( )
//定义方法
var HA={
name:'zhangsan',
birth:2021,
age:function (){
var now=new Date().getFullYear();
return now-this.birth;
}
}
//属性
HA.name
//方法一定带()
HA.age()
调用 HA 的age()方法
2.this
this代表什么?拆开上面的代码看看
function getAge(){
//今年-出生的年
var now=new Date().getFullYear();
return now-this.birth;
}
var HA={
nmae:'zhangsan',
birth:2021,
age:getAge
};
// HA.age() ok
// getAge() NaN window对象
this无法指向的,是默认指向调用它的对象
3.apply
Function.apply(obj,args) 方法能接收两个参数
obj:这个对象将代替Function类里this对象
args:这个是数组,它将作为参数传给Function(args-->arguments)
在JS中可以控制this的指向,通过apply去指定函数指向哪个对象
getAge.apply(HA,[]); //this 指向 HA 这个对象,参数为空
后续内容