函数
函数
函数:一个对象
函数声明
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()
两个参数:
- 作用域
 - 参数 数组或者 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
函数表达式
函数名是引用(指针)

                
            
        
浙公网安备 33010602011771号