js引用类型-Function类型

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

由于函数是对象,因此,函数名实际上是一个指向函数对象的指针,不会绑定某个函数。

创建函数的方式

 1、函数声明 :通常都是使用函数声明的方式创建函数

function name(params) {
  console.log("111");
}

2、函数表达式 :在使用函数表达式的时候,没有必要使用函数名--可以通过变量引用这个函数 

let fun1 = function () {
  console.log("111");
};

3、使用 Function 构造函数 : 不推荐使用,需要解析两次,一次是解析为常规 js代码,二是解析传入构造函数中的字符串。但是,从这种方式创建的时候,我们可以比较清晰的看到  函数是对象,函数名是指针  这个概念性的问题。 

let fun = new Function("num1","num2", "return num1+num2");

函数名-指针 

由于函数名仅仅是指向函数对象的指针,因此函数名与其他其他的指向对象的指针没什么差别。说的直白一点就是,这个函数可以随便取名字,函数表达式的接收变量 也是随意的。

function sum(num1, num2) {
  return num1 + num2;
}
console.log(sum(1, 2));     // 3

// 更换函数的名字  此时 otherSum 也是指向了该函数
let otherSum = sum;
console.log(otherSum(2, 3));// 5

console.log(sum(1, 2));     // 3

// 将最开始的函数名置为 null,消除对函数的引用 
sum = null;

console.log(otherSum(2, 3));// 5 但是不影响 otherSum 对该函数的引用

console.log(sum(1, 2)); // TypeError: sum is not a function

同理,函数表达式也是类似的情况。

函数声明与函数表达式

函数声明和函数表达式都是创建函数的方式,但是在浏览器中的解析存在差异。

变量提升:在代码开始执行前,浏览器的js引擎会先读取函数声明,将函数声明提升到环境顶部,使得之后可以随时随地调用该函数。但是函数表达式则不行,必须等到解析器执行到这个表达式所在的位置,代码才会真正执行。

函数声明:相当于js引擎先将这个函数的函数名当作一个变量,在全局环境声明了,且引用了 sum 这个函数,所以可以在全局调用

console.log(sum(1, 2));    // 3

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

函数表达式:报错信息说的是 初始化之前无法访问“ sum” ,这就表明了 在我 console sun 这个变量的时候,此时这个变量还未被声明,但是在 let sum 之后,console sum 是正常的。也就是上面说的,在我执行到表达式代码之前,sun变量是没有对于 这个函数的引用的,函数表达式创建的函数,只能在代码执行到表达式之后,才能真正执行。

console.log(sum);    //ReferenceError: Cannot access 'sum' before initialization

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

函数内部属性和方法

arguments类数组对象,接收传入函数的所有参数,有一个属性 callee ,指向拥有这个 arguments 对象的函数,当在函数内部继续调用这个函数的时候,可以直接调用函数名(  高耦合,一旦函数名变了,内部调用的函数名也要变 ),也可以使用  arguments.callee(xxx) 来执行该函数( 低耦合,即使函数名改变也不影响,因为 arguments.callee 始终指向的是外部函数)

最明显的就是此类阶乘函数:只能使用 声明的 sum 这个变量去调用函数,一旦 sum 与函数断掉引用,

function sum(num) {
  if (num <= 1) {
    return 1;
  } else {
    // return num * arguments.callee(num - 1);
    return num * sum(num - 1);
  }
}
console.log(sum(5));        // 120
var otherSum = sum;         // 新的变量也引用了这个函数对象

sum = function (params) {   // 改写 sum 的引用
  console.log(params);
};
console.log(sum(4));        // 4

console.log(otherSum(5));   // NaN 因为 sum 已经更改了引用,返回是一个undefined,所以是NaN

 使用 arguments.callee 则不会有这种情况

function sum(num) {
  if (num <= 1) {
    return 1;
  } else {
    return num * arguments.callee(num - 1);
  }
}
console.log(sum(5));        // 120
var otherSum = sum;         // 新的变量也引用了这个函数对象

sum = function (params) {   // 改写 sum 的引用
  console.log(params);
};
console.log(sum(4));        // 4

console.log(otherSum(5));   // 120 ,arguments.callee始终指向的是外部函数,即使外部函数由sum改为otherSum,arguments.callee也会自动更改

this指向 :特殊对象,指向的是函数运行是的环境对象

详情见 另外一篇博文  JS函数–this指向

函数属性和方法

函数是对象,也就存在属性和方法,其中 length 和 prototype 是每隔函数都包含的两个属性

length :表示函数希望接收的形参个数,这个比较简单,可以暂时忽略

prototype :对于js中所有引用类型而言,prototype 是保存他们所有实例方法的真正所在,只不过通过 各自的实例对象访问的。 

类似的有 :valueOf() 、toString() 等等方法 。但是在prototype 上的方法,都是不能被遍历的,for-in,是无法发现的。

有关于 prototype 的相关知识点请参考 这一篇博文 js-原型与原型链

var o = new Test()

o.toString() //"[object Object]"
o.valueOf()  //Test {x: 1}

前面的函数的属性,都是可以通过 prototype 继承而来,但是 apply和call 却不是通过继承而来的,而且也是每隔函数都存在的,具体情况 也可以参考   JS函数–this指向

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在JavaScript中,函数(Function)是一种引用类型。通过使用函数引用类型,我们可以将函数保存为变量,将其作为参数传递给其他函数,或者从函数中返回它。 函数引用类型的一个常见用例是将函数作为参数传递给其他函数。这在高阶函数(Higher-order function)中非常常见。举个例子,假设我们有一个处理数组的函数,可以接受一个回调函数作为参数,并在遍历数组时调用该回调函数。 下面是一个简单的例子: ```javascript // 定义处理数组的函数,并接受一个回调函数作为参数 function processArray(arr, callback) { for (let i = 0; i < arr.length; i++) { callback(arr[i]); } } // 回调函数,用于打印每个数组元素 function printElement(element) { console.log(element); } // 定义一个数组 const myArray = [1, 2, 3, 4, 5]; // 调用processArray函数,传入myArray和printElement函数作为参数 processArray(myArray, printElement); ``` 在这个例子中,`processArray`函数接受一个数组和一个回调函数作为参数。它会遍历数组,并将每个元素作为参数调用回调函数。`printElement`函数是一个回调函数,它在控制台打印每个数组元素。通过将`printElement`函数作为参数传递给`processArray`函数,我们可以实现打印数组的功能。 这个例子展示了如何使用函数引用类型来实现回调机制。函数引用类型的函数可以被保存并传递给其他函数,从而实现更灵活和可配置的代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值