JavaScript函数(上)与java函数的区别

下面从:1、函数的定义2、参数上的区别  3、变量作用域   3.2升权(与变量作用域有关)   等几个方面解释一下JavaScript函数与java函数的区别,并对JavaScript的函数进行详细说明。

  1. 函数的定义 区别

  • java
public class a {
	public static void main(String[] args) {

		System.out.println(new a().sum(1,2)); //==>3  
                //静态方法只能调用静态方法,通过 new a().sum(1,2) 可以达到调用非静态方法的效果

	}
	public int sum(int a,int b) {  // 访问权限  返回值类型 函数名(参数类型 参数名,...)
		return a+b;
	}
	
}
  • JavaScript:
function sum(a,b){ //函数关键字 函数名(参数,参数)
    var c = a + b;
    return c;
}

undefined

sum(1,2);

3

            从定义上看JS的函数定义比java简单,少了访问权限,参数类型等。这里说明JS和java是不相关的,采用两种语言比较是为了理解语言,区分语言,不是它们结构一样。由前边内容所知js只有var一种数据类型表达方式,即然只有一种就没必要在参数前边加参数类型了。而js的函数都是有返回值的,即使不写return 也会默认返回undefined。

           可见,js与java的函数定义方法不一样,是因为它们使用环境不一样造成的。从根本上来说结构还是一样的,只是写法不一样。这时可以会好奇 c = a+b; a、b可能是数字也可能是字符串或者其他,那c的类型是不是就难以确定了,对的c的类型是根据a、b进行确定的,所以js的sum函数可能返回数字也可能返回字符串。为什么:+是一个重载运算符,在数字之间是数学意义上的+,在字符串是将字符串拼接。这也就导致了不同类型结果是不一样的,如sum(true,true)返回2,可见这时是把true转成整数1,在相加。举一反三:因为+是重载运算符,导致返回类型的不确定,如果把+换成-是不是只能返回number类型了呢,这是对的。因为当 - 时,会把字符转换成数字型再计算(数字型字符串转成数字,以非数字字符开头字符串转成NaN)。

      2.参数上的区别

         继续使用上边案例,在java中调用 sum()方法,必须在调用sum()方法时给的参数个数,与类型一样,否则是报错的(sum(1,1,2))。而js因为只有一种类型描述var,返回参数类型就不用管了(不知道这样是对是错),而js对参数个数也没有要求,即您任意给我参数,但我如何处理这些参数就不管您事了。不报错但结果可能和要求的不一样。下面看一下规则:

         1、传少了:自动有参数设用undefined

如:sum(1);

       NaN //可见 a=1,而b = 默认为undefined.相当于 1+undefined = NaN

         2、传多了:自动把多余部分省略
如:sum(1,"2",3);

        3  //可见3没有参加运算,相当于 1+“2”=1+2=3;

这时多与部分就不能调用了吗,能调用。得益与函数内部的arguments变量,该变量是内建变量,每个函数都能调用。

function sum(){ //演示arguments函数的用法
    var a = 0;
    for(var i = 0; i < arguments.length; i++)
        a += arguments[i];  //arguments[n] 表示调用传过来的第n个参数
    return a;
}

undefined

sum(1,2,3,4);

10 //这时我们就可以实现n个参数的相加,举一反三:java上也可以通过数组的方式进行多个参数的相加

sum(1,2,"e",4); 

"3e4" // 1+2+"e"+4; 因为1+2是整数+整数,为3,等于3+“e"+4,而整数+字符串是把整数转字符串后拼接也就得到“3e4"

不要因为arguments[i]就把arguments看成数组,arguments只是一个类似数组的变量。

        3、变量作用域

java上分为成员变量(在本类中类似全局变量)与局部变量:

static int c = 10;  //在类中且不在函数中称为成员变量
	public void sum() {
		int d = 10;//在函数中称为局部变量
	}
	public static void main(String[] args) {
		System.out.println(c);
		System.out.println(d); //报错
		//可见在一个函数中可以访问成员变量,而不能直接访问 一个函数中的局部变量
	}

        而JS中成员变量与局部变量的用法与其它语言一样,但最大的区别就是:js中并不是把代码块当做作用域,而是以函数作为作用域,函数内的是局部变量,函数外的是全局变量  。如java中while(int i)此时i是一个局部变量,作用域是这个循环,而js中只要这while不在函数中,此时i就是一个全局变量。

var global = 1; //全局变量
function js(){
    var locat = 2; //在函数内部,所以是 局部变量
    global++;
    return global;
}

undefined

js();

2

js();

3

locat;
undefined  //在函数外部,并没有找到undefined

注意:如果在函数内声明变量不加var,而该变量默认为全局变量,如把js()内的var locat = 2换成locat = 2;则locat为全局变量

         3.2 升权

注意:java如果两个相同变量名的局部变量的作用域发生冲突是不允许的(本人认识),而两个相同变量名如果一个是成员变量,一个局部变量。局部变量的作用域会覆盖成员变量作用域。

int i = 0; //可见,java允许全局变量与局部变量的变量名相同
	public static void main(String[] args) {
		for(int i = 0; i < 2; i++) {
			for(int i = 0; i < 2; i++) {
			//报错,因为两个i既都是局部变量,作用域还冲突。java不允许
				System.out.println(i);
			}
		}
		
		for(int i = 0; i< 2; i++) {
		//不报错,虽然在这个方法中有三个i,但作用域是不冲突的。而且它会覆盖全局
		//变量i的作用域
			System.out.println(i);
		}
	}

而js允许下面的写法(java不允许)

for(var i = 0; i<2; i++){
    for(var i = 0; i<3; i++){ //这个i会覆盖上面的i
        alert(i);
    }
}

上面简单说了java会作用域的规定与js(c,c++也允许js的写法)的区别。下面说js独有的升权:


var a = 123;

undefined

function f(){
    alert(a);
    var a = 1; 
    alert(a);
}

上面代码,如果以java的思维,弹出警告分别为 123    1这对java来说是对的,但js却显示为 undefined 1。因为:

js中函数内被声明的所有变量都会被移动(或者是提升)到函数最开始的地方。注意,被提升的只有变量的声明。

也就是说上述代码等价于:

var a = 123;

undefined

function f(){
    var a; //此时局部变量a,已经覆盖了全局变量a
    alert(a);
    a = 1; 
    alert(a);
}

现在看:第一个alert,因为a还没有赋值,默认就是undefined.第二个alert因为a已经赋值1。所以js显示undefined 1也是对的。

作用域链

作用域链指的就是变量的作用域,js中变量的作用域是以函数来划分的,在函数内是局部变量,在函数外是全局变量。

var global = 1;
undefined
function outer(){
  var outer_local = 2;
  function inner(){ //它做为一个函数的子函数,可以访问父函数的变量,父函数无法访问它的变量
    var inner_local = 3;
    return inner_local + outer_local + global;
  }
  return inner();
}
undefined
outer();
6

突破作用域链

上面说了作用链,全局访问不了局部变量,就是子能访问父,父不能访问子。突破作用链解决父访问子的问题

方法1:通过返回一个函数突破

var F = function(){
  var b = "local variable";
  var N = function(){
    return b;
  };
  return N;
};
undefined
var c = F();
undefined
c();
"local variable"

首先在全局是访问不了局部变量b的,而N函数作为F函数的一个子函数是可以访问b,此时把N函数返回在全局变量,在全局下就可以通过返回的N函数访问局部变量b

方法2:通过在函数内定义一个全局变量(不加var)突破

var F = function(){
  var b = "local variable";
  var N = function(){
    return b;
  };
  inner = N;
};
undefined
inner();
"local variable"

虽然inner是一个全局变量,但是它定义在函数内,所以它可以访问变量b

3、循环中闭包常见错误

function F(){
  var arr = [],i;
  for(i = 0; i < 3; i++){
    arr[i]  = function(){
      return i;
    };
  }
  return arr;
}
undefined
var arr = F();
undefined
arr[0]();
3

可见输出错误,这是因为arr[0]存放的是 function(){ return i; }; 而i在for执行完成后i变成了3。可以通过即时函数解决

function F(){
  var arr = [],i;
  for(i = 0; i < 3; i++){
    arr[i] = (function(x){
      return function(){ return x;};}(i));
  }
  return arr;
}
undefined
var arr = F();
undefined
arr[0]();
0

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值