js基础学习——引用类型中的Function类型

1.创建函数

函数也是对象。每个函数都是Function的实例,都与其他引用类型一样具有属性和方法。

  • function关键字:
//语法格式:
function fn(){};
  • 函数表达式
//语法格式:
var fn = function(){};

函数名仅仅是指向对象的指针,因此函数名与包含对象指针的其他变量没有什么不同。
不带圆括号的函数名是访问函数指针,而不是调用函数。

2.没有重载

  • 由于不存在函数签名的特性,所以ECMAscript函数也就不能重载。
  • 只会出现后定义的同名函数覆盖先定义的函数的情况。
// js函数不能重载
var add = function addSome(num) {
    return num + 100;
}
add = function addSome(num) {
    return num + 200;
}
console.log(add(100));//300

3.函数声明与函数表达式

  • 在解析器解析js代码时,会先读取函数声明,使其在执行任何代码前可用;函数表达式只有在代码执行到所在行才会被真正解释执行。
  • 简单理解就是:函数声明创建的Function实例具有函数提升的特性。
alert(sum(1,1));//2,函数提升,虽然声明在后,但是依然可以先调用后声明
function sum(num1,num2){
    return num1 + num2;
}

console.log(sum1(10,10));//sum1 is not a function
var sum1 = function(num1,num2){
    return num1 + num2;
}

4.作为值的函数

  • 比较典型的就是回调函数。
  • 因为函数名本身就是变量,所以函数也可以作为值传递给另一个函数。
  • 也可以将函数作为另一个函数的结果返回。
// 可以作为参数传递函数,也可以将一个函数作为另一个函数的返回值
function fn(funct){
    return function fun(){
        console.log('作为返回值的函数');
    }
}
function funct() {
    console.log( '1');
    
}
fn(funct());//1
var result = fn();
result();//作为返回值的函数

4.1 函数作为返回值的用处

根据某个对象属性对数组排序时,传递给sort()的比较函数:

// 2.函数作为返回值在sort方法中的用法
function compareFun(prooertyName){
    return function compare(object1, object2){
        value1 = object1[prooertyName];
        value2 = object2[prooertyName];
        if(value1 < value2){
            return -1;
        }else if(value1 > value2){
            return 1;
        }else{
            return 0;
        }
    }
}
// 测试一下:
var data = [{
    name : '张三',
    age : 12
},
{
    name: '李四',
    age: 20
}
]
        
data.sort(compareFun('age'));
console.log(data);//0: {name: "张三", age: 12}
                  //1: { name: "李四", age: 20 }

5.函数内部属性

  • arguments:arguments是一个类数组(伪数组)对象,包含着传入函数的所有参数;主要用途是保存函数参数。
    该对象还有一个名为callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。
// 1.阶乘可以通过递归函数实现
function fn(num){
    if(num <= 1){
        return 1;
    }else{
        return num * fn(num - 1)
    }
}
var result = fn(5);
console.log(result);//120
        
// 但是这样写的弊端在于,函数的执行和函数名耦合度较高
// 这时可以用arguments.callee属性来解决

// 2.改进后的阶乘函数
function fn(num){
    if(num <= 1){
        return 1;
    }else{
        //arguments.callee()指向拥有该arguments对象的函数:fn()
        return num * arguments.callee(num - 1);
    }
}
var result = fn(5);
console.log(result);//120
  • this:this引用的是函数据以执行的环境对象,当在网页的全局作用域下调用函数时,this指向的是window。
  • caller:函数对象属性,该属性中保存调用当前函数的引用(简单理解就是谁调用了这个函数),如果是在全局作用域下调用该函数,caller值为null。
// =====this=====
// 全局作用域下this指向window对象
function test(){
    console.log(this);
}
test();//Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}
//关于caller属性
// caller属性
function testFn(){
    console.log(testFn.caller);
    testFn1();
    function testFn1(){
        // testFn调用了该函数,caller保存的是引用testFn
        //这里也可以使用arguments.callee.caller
        console.log(testFn1.caller);//ƒ testFn()
    }
}
testFn();//全局作用域下返回null

callee和caller小结:
简单理解:callee指向包含拥有某个arguments对象的函数;caller指向调用了该函数的函数。

5.1 严格模式下caller和callee

  • 严格模式下访问arguments.callee会报错;
  • ES5定义了arguments.caller属性,严格模式下访问会报错,非严格模式下始终是undefined;
  • 严格模式下不能为函数的caller属性赋值。

6.函数属性和方法

每个函数都具有的属性:length和prototype。

  • length属性:表示函数希望接收的的命名参数的个数。
// length属性表示函数接收的命名参数个数
function fn1(){
    console.log(fn1.length);
}
function fn2(a,b){
    console.log(fn2.length);
}
fn1();//0
fn2();//2
  • prototype原型对象:保存着所有实例方法,不可被枚举(详细说明请看后续)。

每个函数都具有的方法:apply、call、bind;
这三个方法的作用在于:修改函数的this指向,扩充函数作用域。

  • apply():可以调用函数,接收两个参数:this指向、参数数组(或者直接是arguments对象)
//语法格式
fn.apply(this指向,[arg1,arg2....])

// 1.apply():调用函数,修改函数的this指向,接收数组形式的参数
function fn(num1,num2){
    return num1 + num2;
}
function fn1(num1,num2){
    // 调用fn函数,并将fn函数this指向改为指向fn1
    return fn.apply(this,arguments);
}
console.log(fn1(10, 10));//20
  • call():作用和apply()方法一样,不同之处在于其接收第二个参数的格式不同,call方法接受的参数都是直接传递进来的,apply接受的第二个参数以数组的形式传递。
// 2.call():调用函数,修改this指向,参数直接传递给call
function callFn(num1,num2){
    return num1 * num2;
}
function callFn1(num1,num2){
    // 修改this指向,调用callFn函数,参数直接传入
    return callFn.call(this,num1,num2);
}
console.log(callFn1(10,10));//100

注意:在严格模式下,未指定环境对象就调用函数,this指向不一定是window对象,除非把函数添加到某个对象或者调用apply或call方法,否则this值就是undefined。

  • bind():修改this指向,但是不会调用函数,传参方式与call方法一致。

供学习交流使用,如有不足的地方,欢迎评论区交流。
业精于勤,荒于嬉,祝大家学习更上一层楼。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值