3、JavaScript函数

3.1 函数的定义和调用

定义方式一 (建议使用)

//定义绝对值函数
function abs(x) {
	if (x >= 0) {
		return x;
	} else {
		return -x;
	}
}
  • 一旦执行到 return 时,函数就执行完毕,并将结果返回。

  • 如果没有 return 语句,函数执行完毕后也会返回结果,只是结果为 undefined 。

定义方式二

//function (x) { ... } 是一个匿名函数,它没有函数名。但这个匿名函数赋值给了变量abs,通过变量abs就可以调用该函数。 
var abs = function(x) {
	if (x >= 0) {
		return x;
	} else {
		return -x;
	}
};

方式一与方式二完全等价,注意:方式二需要在函数体末尾加一个分号,表示赋值语句结束。

调用函数

abs(-5);   // > 5
abs(5);    // > 5

参数问题:JavaScript 可以传任意个参数,也可以不传参数

//假设不存在参数,如何规避?
var abs = function (x) {
      if (typeof x!== 'number'){
        //手动抛出异常
        throw 'Not a number!';
      }
      if (x >= 0) {
        return x;
      } else {
        return -x;
      }
    };

arguments

JavaScript免费赠送的关键字,代表传递进来的所有参数是一个数组

var abs = function (x) {
      console.log('x=>' + x);
      for (var i=0; i<arguments.length; i++) {
        console.log('arg ' + i + ' = ' + arguments[i]);
      }
      if (x >= 0) {
        return x;
      } else {
        return -x;
      }
    };

问题:arguments包含所有的参数,我们有时候想使用多余的参数来进行附加操作,需要排除已有的的参数。

rest

以前:

if (arguments.length>2){
   for (var i=2; i<arguments.length; i++) {}
}

ES6 的新特性~ rest,获取除了已经定义的参数之外的所有参数

function aaa(a,b,...rest){
   //rest参数只能写在最后面,必须用...标识
   console.log("a=>"+a);
   console.log("b=>"+b);
   console.log(rest);
}
aaa(1,1,1,1,1)
> a=>1
> b=>1
> (3) [1, 1, 1]

3.2 变量的作用域

在JavaScript中,var定义的变量实际上是由作用域的

  • 假设在函数体中声明,则在函数体外不可以使用(非要实现的话,需要使用闭包)

    'use strict';
    function a(){
        var x = 1;
        x = x + 1;
    }
    x = x + 2; //Uncaught ReferenceError: x is not defined
    
  • 如果两个函数使用了相同的变量名,只要在函数内部,就不冲突

    function a1(){
        var x = 1;
        x = x + 1;
    }
    function a2(){
        var x = 1;
        x = x + 1;
    }
    
  • 内部函数可以访问外部函数的成员,反之则不行

    function a1(){
        var x = 1;
        function a2(){
        	var y = x + 1; //2
        }
        var z= y + 1; // Uncaught ReferenceError: z is not defined
    }
    
  • 假设内部函数与外部函数的变量重名

    function a1(){
        var x = 1;
        function a2(){
        	var x = 'a';
            console.log('内部:'+x);
        }
        console.log('外部:'+x);
        a2(); //内部:a
    }
    a1(); //外部:1
    
  • 假设在JavaScript中函数查找变量从自身函数开始,从“内”向“外”查找。如果内部函数定义了与 外部函数重名的变量,则内部函数的变量将“屏蔽”外部函数的变量。

提升变量的作用域

function a(){
    var x = 'x' + y;
    console.log(x);
    var y = 'y';
} //Uncaught ReferenceError: x is not defined

说明:JavaScript执行引擎,自动提升了y的声明,但不会提升变量y的赋值,这个是在JavaScript建立之初就存在的特性。

function a(){
    //var x,y,z...;
    //养成规范:所有的变量定义都放在函数的头部,不要乱放,便于代码维护
    var x = 'x' + y,
    	y = 'y',
        z,a,b,c;  //undefined
}

全局作用域

var x = 1;
function  f(){
    console.log(x);
}
console.log(x);
  • 全局对象 window

  • var x = 'xxx';
    alert(x); //直接调用alert()
    window.alert(x);  //alert()本身也是一个window变量,可以通过window对象来调用
    alert(window.x); //默认所有的全局变量,都会绑定在window对象下,可以通过window对象来调用
    
  • 玩一下:发现JavaScript实际上只有一个全局作用域。任何变量(函数也视为变量),如果没有在当前函数作用域中找到,就会继续往上查找,最后如果在全局作用域中也没有找到,则报 ReferenceError 错误。

    'use strict';
    window.alert('调用window.alert()');
    // 把alert保存到另一个变量:
    var old_alert = window.alert;
    // 给alert赋一个新函数:
    window.alert = function () {}
    alert('无法用alert()显示了!');
    // 恢复alert:
    window.alert = old_alert;
    alert('又可以用alert()了!');
    
    
  • 规范:

    • 由于我们所有的全局变量会绑定到 window 上。如果不同的JavaScript文件使用了相同的全局变量,就会发生冲突。

    • 减少冲突:把自己的代码全部放入自己定义的唯一名字空间中,降低全局命名冲突的问题

      //唯一全局变量
      var JiangApp = {};
      
      //定义全局变量
      JiangApp.name = 'jiang';
      JiangApp.add = function (a,b){
      	return a + b;
      }
      

局部作用域 let(建议使用)

function a(){
    for (i = 0; i < 100; i++) {
        console.log(i);
	}
console.log(i+1);  // 101 i出了这个作用域还可以使用
    
//ES6 引入let关键字,解决局部作用域冲突的问题
    function a(){
        for (let i = 0; i < 100; i++) {
            console.log(i);
        }
    console.log(i+1);  // Uncaught ReferenceError: z is not defined

常量 const

  • 在 ES6 之前,定义常量的方法:只要用全部大写字母命名的变量就是常量,建议不要修改这样的值

  • 在 ES6 引入了常量关键字const

    const PI = 3.14;
    PI = 3; //Uncaught TypeError: Assignment to constant variable.
    PI; // 3.14
    

3.3 方法

定义方法

方法就是把函数放在对象的内部,对象只有两个东西:属性和方法

var me = {
  name:'jiangjiang',
  birth:2002,
  age: function (){
    var now = new Date().getFullYear();
    return now-this.birth; //this默认指向调用它的那个对象
  }
}
//调用属性
me.name;  //'jiangjiang'
//调用方法:一定要带()
me.age(); //21

拆开写:

function getAge() {
  var now = new Date().getFullYear();
  return now - this.birth;
    //此处this是无法改变指向的,默认指向调用它的那个对象
}
var me = {
  name: 'jiangjiang',
  birth: 2002,
  age: getAge
};
//调用
me.age(); // 21, 正常结果
getAge(); // NaN

apply 在Js中可以控制this的指向

getAge.apply(me,[]); //this指向了me这个对象,参数为空
// 21, 正常结果
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秃头酱酱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值