函数

函数

函数:一个对象

函数声明

function sum(num1, num2){
  return num1 + num2;
}

函数表达式定义函数

var sum = function(num1, num2){
  return num1 + num2;
};

使用Function函数构造器时,可以接受收仍以数量的参数,但最后一个参数被看作函数体。

var sum=new Function('a','b','c=a+b;return c')
console.log(sum(1,2));// 3

函数名:指向函数对象的指针(引用)

var sum=function(a,b){
    return a+b
}
var a=sum
console.log(a(1,2));//3

arguments 参数

函数定义时,规定的参数只是为了使用的时候方便一些,不是必须的
本质上是通过arguments对象访问参数的,它与数组类似(但不是Array的实例) 可以用[ ]访问元素

function def(a,b){
    console.log(a);
    console.log(arguments[3]);
}
def(1,2,3,4,5)

利用arguments.length遍历参数

function def(a,b){
    for(let i =0;i<arguments.length;i++){
        console.log(arguments[i]);
    }
}
def(1,2,3,4,5)

函数命名参数和arguments的同步关系

修改对应的arguments,命名参数会被同步修改

function change(a,b){
    arguments[1]=123
    console.log(b);//123
}
change(1,2)

修改命名参数时,arguments也会被对应修改

function change(a,b){
    b=123
    console.log(arguments[1]);//123
}
change(1,2)

参数不存在时 ,赋值arguments,命名参数仍然是undefined

function change(a,b){
    arguments[1]=123
    console.log(b);//undefined
}
change(1)

利用arguments的callee属性 获取当前函数指针

var p=null;
function def(){
    p=arguments.callee;
    console.log('run');
}
def();//run
p();//run

配合递归使用,可以在不使用函数名调用自身

function def(now){
    console.log(now);
    if(now==10){
        return 
    }
    arguments.callee(now+1);//0 1 2 3 4 5 6 7 8 9 10
}
def(0)

caller属性

返回调用当前函数的对象

this 函数内部的特殊对象

在哪调用函数,this属于哪个域

window.ss=123
function def(){
    console.log(this.ss);//123  this=window
}
function def2(){
    function def3(){
        this.name='zhangsan'//this仍然是window
        console.log('def2',this.ss);
    }
    def3();
}
def();//123
def2();//def2 123
console.log(window.name)//张三
    function Person(name,age){
        this.name=name;
        this.age=age
    }
    function getAge(){
        return this.age;
    }
    var p=new Person('zhangsan',12)//一个新的域 this属于对象p
    console.log(window.getAge());//undefined
    console.log(getAge());//undefined
    p.getAge=getAge//不能直接调用 p.getAge() 不存在该方法
    console.log(p.getAge());//12

apply(),call()和bind()方法

使得在不同的域环境下调用函数

域环境取决于 xxx.function() 中的xxx 。

var p1={
    fullName: function(){
        return this.firstName+this.lastName;
    },
    getInf: function(city,flag){
        return 'name:'+this.firstName+this.lastName+';city:'+city;
    }
    
}
var p2={
    firstName:'zhang',
    lastName:'san',
    city:'shanghai'
}
var res=p1.fullName.apply(p2)
console.log(res);//zhangsan
p2.fullName=p1.fullName;//引用的p1的函数fullName 但是作用域不同
res=p2.fullName();//作用域是p2
console.log(res);//zhangsan
var res2=p1.getInf.apply(p2,[p2.city,'1']);//必须将参数放到列表里
console.log(res2);//name:zhangsan;city:shanghai
var res3=p1.getInf.call(p2,p2.city,'1');//必须将参数放到列表里
console.log(res3);//name:zhangsan;city:shanghai

apply()

两个参数:

  1. 作用域
  2. 参数 数组或者 arguments
var p1={
    funllNmae: function(){
        return this.firstName+this.lastName;
    },
    getInf: function(city,flag){
        console.log(flag);
        return 'name:'+this.firstName+this.lastName+';city:'+city;
    }
    
}
var p2={
    firstName:'zhang',
    lastName:'san',
    city:'shanghai'
}
var res=p1.funllNmae.apply(p2)
console.log(res);//zhangsan
p2.funllNmae=p1.funlllNmae;
p2.funllNmae();//zhangsan

var res2=p1.getInf.apply(p2,[p2.city,'1']);//必须将参数放到列表里
console.log(res2);//name:zhangsan;city:shanghai
console.log(res3);//name:zhangsan;city:shanghai

call()

与apply不同点:参数需要逐个列出,不能放到数组里

var res3=p1.getInf.call(p2,p2.city,'2');//必须逐个列出所有参数

bind()

给函数绑定对象域 也能传递参数 (不能用数组传)

function Person(name,age,job){
    console.log('test');
    this.name=name;
    this.age=age;
    this.job=job;
    this.sayName=function(){
        console.log(this.name);
    }
}
var obj={};
var bindTest=Person.bind(obj,'lisi',18,'c');
bindTest()
console.log(obj);
//obj={name: 'lisi',age:18,job:'c',sayName:[Function (anonymous)]}

实现函数作用域的扩充

    window.color='red'
    var obj={color:'blue'}
    function sayColor(){
        console.log(this.color);
    }
    
    sayColor()//red
    sayColor.apply(obj)//blue

按值传递

例1:

function change(a){
	a+=1	
}
let a=1;
change(a);
console.log(a);//a的值仍是1

例2:

function Person(name,age){
    this.name=name;
    this.age=age;
}
//构造函数
function change(person){
person.name="美丽传说";
person=new Person('阿甘正传',10);//此处开辟了新空间
}
var p=new Person("西西里",20);
console.log(p.name);//此处输出为西西里
change(p);
console.log(p.name);//此处输出为美丽传说 不是 阿甘正传

当参数是对象时,传递的时对象的地址

person.name='美丽传说'

  • 这是在原先对象的地址上修改属性值

person=new Person('阿甘正传',10)

  • 此时person变量的地址发生了改变 指向了新的一个Person对象,与原先的对象没有关系了

函数重复声明

js不存在重载,不会动态匹配参数选择合适的函数,而是直接覆盖之前的同名函数

function def(a){
    console.log(a);
}
function def(a,b){
    console.log(a);
    console.log(b);
}
def(1)

函数作用域

var a=0
function def1(){
    var b=1;
    function def2(){
        var temp=b;//使用的是def1的b
        b=a;//使用的是全局的a
        a=temp;//使用的是def2的temp
    }
    def2()
    //不可以使用def2的temp
}
def1()
//不可以使用b,temp
console.log(a);

不存在块级作用域

{}内的代码(代码块)不存在自己的作用域 ,作用域属于就近的函数或者全局

if(true){
	var a=123; //属于全局变量
}
console.log(a);//123

函数表达式

函数名是引用(指针)

posted @ 2021-11-15 21:17  CCCC_03  阅读(47)  评论(0)    收藏  举报