函数初识

2019-06-19  本文已影响0人  lyp82nkl

函数的5种声明方式

具名函数

 function f(x,y){
     return x+y
 }
 f.name // 'f'

匿名函数

 var f
 f = function(x,y){
     return x+y
 }
 f.name // 'f'

具名函数赋值

 var f
 f = function f2(x,y){ return x+y }
 f.name // 'f2'
 console.log(f2) //f2 is not defined

window.Function

var f = new Function('x','y','return x+y')

箭头函数

 var f = (x,y) => {
     return x+y
 }
f(1,2)//调用方法函数名(参数1,参数2)    3
//如果函数体内只有一条语句,大括号和return可以省略,也就是说在不写大括号的情况下,它默认就return
 var sum = (x,y) => x+y
//如果函数只有一个参数,小括号可以省略
 var n2 = n => n*n

函数的执行

var z;
function f2(){
    console.log(z)
}
z=1;
f2.call()//1

上面的代码函数调用后打印出来的z是1,而不是undefined,是因为在函数f2声明的时候并未获取和打印出z这个变量,而是在f2调用的时候才去获取的,就相当于只要在函数调用的时候打印的z都是与函数调用这段代码最近的那个z。也就是说一个函数里面获取一个变量,是在函数调用之后才去获取的(获取的变量是与函数调用这个代码前面的最新一次的变量值),而不是函数声明的时候就获取。

上面的代码其实你也可以看成:

var z;
z=1;
function f2(){
    console.log(z)
}
f2.call()//1

将执行的函数赋值给一个变量

function fn(){
    console.log('aaa');
    return 'zzz'
}
var result = fn()  //'aaa'
result  //'zzz'

如何调用函数

函数到底是什么?
var obj = {
  //这里的test就是一个方法,也可以说是函数
  test: function(){
    console.log('zzz')
  }
}
//方法(函数)调用
obj.test()

函数传参

var p = 2;

function f(p) {
  p = 3;
}
f(p);

p // 2

上面代码中,变量p是一个原始类型的值,传入函数f的方式是传值传递。因此,在函数内部,p的值是原始值的拷贝,无论怎么修改,都不会影响到原始值。

函数参数是复合类型的值(数组、对象、其他函数),传递方式是传址传递(pass by reference)。也就是说,传入函数的原始值的地址,因此在函数内部修改参数,将会影响到原始值。

var obj = { p: 1 };

function f(o) {
  o.p = 2;
}
f(obj);

obj.p // 2

上面代码中,传入函数f的是参数对象obj的地址。因此,在函数内部修改obj的属性p,会影响到原始值。

function fn(obj){
    obj.name = 'ff'
    obj = new Object()
    obj.name = 'man'
}
var person = new Object()
fn(person)
console.log(person.name) //'ff'

1.上面代码因为是将一个引用类型作为参数,所以传入的是一个引用地址(ADDR 26),也就是形参obj的值实际上就是person的引用地址
2.然后对这个ADDR 26添加一个name属性obj.name = 'ff'
3.重新对形参obj进行赋值,指向另一个内存地址(ADDR 34)
4.在ADDR 34上添加name属性obj.name='man'
5.所以最后person.name也就是person的引用地址(ADDR 26)里的name,也就是‘ff’

f()与f.call()

function f(x,y){return x+y};
f.call(undefined,1,2)   //3
//相当于 f(1,2)

f 与 f.call()区别:
f 指的是这个对象
f.call() 是执行这个对象的函数体

this和arguments

function f(){
    'use strict'
    console.log(this)
    console.log(arguments)
    return undefined
}
f.call(1,2,3) // this 为 1,arguments 为 [2,3]

上面的函数f里面写入了打印this和arguments两条语句;当执行f.call(undefined,1,2)命令时,得到this是window(chorme浏览器显示的大写的Window其实是小写的window),arguments(实参)是一个伪数组,里面有1和2两个值,这里注意为什么this不是undefined,因为默认情况下this都会变成window,所以要想得到undefined就要开启严格模式

上面的代码使用了 ‘use strict’ 会变成严格模式。开启严格模式就不会乱改 this ,那么 this 原本的值就会打印出来。这样再给 undefined 真的是 undefined ,不会变成window。

f.call(1)     //1    
f.call('sss')  // sss

this 就是 call 的第一个参数

伪数组:如果你的proto(原型链中)没有Array.prototype这一环,就是伪数组。同时你的原型链的原型链也不是Array.prototype,整个原型链中跟Array.prototype没有一点 关系,就是完完全全的伪数组。
arguments 的proto 直接指向了 object.prototype ,没有Array.prototype这一环,所以是伪数组。

对象中的函数

var init=function(){
  console.log('aaa')
}
var obj = {
  init: function(){
    console.log('zzz');
    //这里的init是上面的变量init,而不是属性init,因为对象里的属性必须对象.属性,而不能直接写属性
    init()
  }
}

obj.init()
//zzz
//aaa

同名参数

如果有同名的参数,则取最后出现的那个值。

function f(a, a) {
 console.log(a);
}
 
f(1, 2) // 2

上面代码中,函数f有两个参数,且参数名都是a。取值的时候,以后面的a为准,即使后面的a没有值或被省略,也是以其为准。

function f(a, a) {
 console.log(a);
}
 
f(1) // undefined

调用函数f的时候,没有提供第二个参数,a的取值就变成了undefined。这时,如果要获得第一个a的值,可以使用arguments对象。

function f(a, a) {
 console.log(arguments[0]);
}
 
f(1) // 1
var a = (1,2)
a  //2

上面的代码a的值是2,多个值用小括号括起来,但取值的时候总是以后面的为准

设置默认参数值

function b(obj,str='z'){
    return{
        obj,str
    }
}

上面的函数b里面有两个参数,其中第二个参数str,写成了str='z'意思是如果你不传第二个参数,它默认就相当于你传了一个'z'

//调用b函数,不传入第二个参数,str就是默认的'z'
b({name:'ff'})
//当调用函数时传入第二个参数,那个str就会是你传入的值
b({name:'ff'},'fangfang')

另外如果函数表达式中需要传参,而你调用的时候没有传,那么这个参数就是undefined,可以通过参数是否等于undefined来判断有没有传参数
上一篇下一篇

猜你喜欢

热点阅读