Js函数深入理解-内部属性与递归

Js函数深入理解-内部属性与递归

函数里面有两个特殊的对象:argumentsthis

arguments详解

用于保存参数

function a(num1,num2){

console.log(num1)   //123

console.log(num2) //456

console.log(arguments)  ?

}

a(123,456)

 

console.log(arguments) 打印出来是这样的

Js函数深入理解-内部属性与递归_第1张图片


arguments是个类数组对象,传的参数都存储到这个数组中,因此可以这么访问

function a(num1,num2){

console.log(arguments[0])  //123

console.log(arguments[1])  //456

}

a(123,456)

由此可知,num1,num2两个参数可以不写


有时候我们需要根据参数的个数进行判断它执行哪个条件语句,这时我们可以用到arguments.length这个属性

function a(){

if(arguments.length == 1){//传一个参数时执行

console.log(arguments[0]);

}

if(arguments.length == 2){//两个参数时执行

console.log(arguments[0]+arguments[1]);

}

}

a(10); //10

a(10,20); //30

 

arguments还有个属性callee,它指向的是函数自己,递归里面用得到

 

this详解

var name='lisi';

function a(){

console.log(this);  //window

console.log(this.name);  //lisi

}

a();

简单的说,谁调用a这个函数,this就指向谁。这里的a()可以看成是window.a(),所以this引用的是window

 

再看下面的例子

    var name='lisi';

var str = {name:'zhsan'};

str.a = a;

function a(){

console.log(this);  //Object {name: "zhsan"}

console.log(this.name);  //zhsan

}

str.a();

这里把函数赋给对象str,因此str调用a时,this指向的是str这个对象。

 

注意:函数名只是个指针,window.a()str.a()都指向的是同一个函数

 

apply()call的用法

函数有两个参数,第一个是作用域(全局或者个别对象),第二个是数组/对象

function sum(num1, num2){

return num1 + num2;

}

function callSum1(num1, num2){

return sum.apply(this, arguments); // 传入 arguments对象

}

function callSum2(num1, num2){

return sum.apply(this, [num1, num2]); // 传入数组

}

console.log(callSum1(10,10)); //20

console.log(callSum2(10,10)); //20

这里的this指向谁呢?指向sum这个函数??

NO!callSum1(10,10)调用它的是全局对象,因此this指向window

 

注意:在严格模式下,未指定环境对象而调用函数,则 this值不会转型为 window。除非明确把函数添加到某个对象或者调用apply()call(),否则this 值将是undefined

 

applycall强大之处是扩展作用域,简单的说指定执行该函数的环境

前面的例子可以改成下面:

var name='lisi';

var str = {name:'zhsan'};

 

function a(){

console.log(this.name);  

}

a.call(this) //lisi

a.call(window) //lisi

a.call(str)  //zhsan

 

函数递归

例子:

function sum(x){

if(x<1){

return x;

}

return x+sum(x-1);

}

console.log(sum(10))  //55

 

再看下面例子

function sum(x){

if(x<=1){

return 1;

}

return x+sum(x-1);

}

var test = sum;

sum = null; //销毁这个函数名

console.log(test(10)) //Uncaught TypeError: sum is not a function

 

但如果写成这样:

function sum(x){

if(x<=1){

return 1;

}

console.log(this)

return x+arguments.callee(x-1);

}

var test = sum;

sum = null;

console.log(test(10)) //55

之前提到过arguments.calleecallee属性,它指向函数本身,sum被销毁,只是销毁名字,而函数依然存在

因此写递归的话使用arguments.callee比较好,但是在严格模式下不能访问arguments.callee这个属性,因此也会报错。

 

下面是最完善的写法:

var sum = (function f(x){

if(x<=1){

return 1;

}

return x+f(x-1);

})

 

var test = sum; //已经把test指向了f(x)

sum = null; //销毁后并不影响 test

 

console.log(test(10)) //55


你可能感兴趣的:(js程序设计)