Function函数

Function

Function 是 JavaScript 中的一个内置对象,用于表示函数或方法。每一个函数都是 Function 类型的实例。你可以使用 Function 构造函数来创建新的函数,尽管这种方式不如使用函数声明或函数表达式常见。

1. Function 构造函数

Function 构造函数允许你动态地创建函数。它的语法如下:

new Function ([arg1[, arg2[, ...argN]],] functionBody)
  • arg1, arg2, ... argN:函数的参数,这些参数是字符串形式的。
  • functionBody:函数的主体,也是一个字符串。

例如:

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

尽管 Function 构造函数可以实现动态函数创建,但这种方式通常不推荐,因为它可能导致代码难以理解和维护,并且可能增加性能开销。

2. Function 类型的属性和方法

Function 类型有一些属性和方法,用于获取或操作函数。

属性:
  • length:返回函数期望的参数个数,不包括 rest 参数。
方法:
  • call():调用一个具有给定 this 值和作为一个数组(或类似数组对象)提供的参数的函数。
  • apply():调用一个具有给定 this 值和以一个数组(或类似数组对象)的形式提供的参数的函数。
  • bind():创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,其余的参数将作为新函数的参数供调用时使用。

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

除了使用 Function 构造函数,我们更常使用函数声明和函数表达式来创建函数。

函数声明:
function myFunction(a, b) {
  return a + b;
}
函数表达式:
var myFunction = function(a, b) {
  return a + b;
};

这两种方式比使用 Function 构造函数更常见,因为它们提供了更好的可读性和性能。

4. 闭包和函数作用域

在 JavaScript 中,函数可以访问和操作其外部词法环境(lexical environment)的变量,这种特性被称为闭包(closure)。闭包是 JavaScript 中一个强大的概念,它允许我们创建可以在其外部环境中保留和操作数据的函数。

总结

Function 在 JavaScript 中是一个基础且重要的对象,它用于表示函数。尽管我们可以使用 Function 构造函数来创建函数,但更常见和推荐的方式是使用函数声明和函数表达式。此外,了解闭包和函数作用域对于深入理解 JavaScript 中的函数非常关键。
每个 JavaScript 函数实际上都是一个 Function 对象。运行 (function(){}).constructor === Function // true 便可以得到这个结论。

实例属性

arguments

是一个对应于传递给函数的参数的类数组对象。

function func1(a, b, c) {
  console.log(arguments[0]);
  // expected output: 1

  console.log(arguments[1]);
  // expected output: 2

  console.log(arguments[2]);
  // expected output: 3
}

func1(1, 2, 3);
Function.length

length 属性指明函数的形参个数。

function func1() {}

function func2(a, b) {}

console.log(func1.length);
// expected output: 0

console.log(func2.length);
// expected output: 2

实例方法

Function.length

length 属性指明函数的形参个数。

function func1() {}

function func2(a, b) {}

console.log(func1.length);
// expected output: 0

console.log(func2.length);
// expected output: 2
apply()的语法

call 与 apply 用于显示的设置函数的上下文,两个方法作用一样都是将对象绑定到 this,只是在传递参数上有所不同。

call 和 apply 都是为了解决改变 this 的指向。作用都是相同的,只是传参的方式不同。

call 可以接收一个参数列表

apply 只接受一个参数数组。

与 bind 不同 call/apply 会立即执行函数

function show(title) {
  console.log(`${title + this.name}`);
}
let lisi = {
  name: "李四",
};
let wangwu = {
  name: "王五",
};
show.call(lisi, "用户1:");
show.apply(wangwu, ["用户2:"]);

// 用户1:李四
// 用户2:王五
Function.prototype.bind()

bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。

const module = {
  x: 42,
  getX: function () {
    return this.x;
  },
};

const unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// expected output: undefined

const boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// expected output: 42
Function.prototype.toString()

toString() 方法返回一个表示当前函数源代码的字符串。

function sum(a, b) {
  return a + b;
}

console.log(sum.toString());
// expected output: "function sum(a, b) {
//                     return a + b;
//                   }"

console.log(Math.abs.toString());
// expected output: "function abs() { [native code] }"
Function.prototype.call()

语法

function.call(thisArg, arg1, arg2, …)

call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。

返回值

  • 使用调用者提供的 this 值和参数调用该函数的返回值。若该方法没有返回值,则返回 undefined。
function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  Product.call(this, name, price);
  this.category = "food";
}

console.log(new Food("cheese", 5).name);
// expected output: "cheese"
var animals = [
  { species: 'Lion', name: 'King' },
  { species: 'Whale', name: 'Fail' }
];

for (var i = 0; i < animals.length; i++) {
  (function(i) {
    this.print = function() {
      console.log('#' + i + ' ' + this.species
                  + ': ' + this.name);
    }
    this.print();
  }).call(animals[i], i);
}
//#0 Lion: King
// #1 Whale: Fail

使用 call 方法调用函数并且指定上下文的 ‘this’

在下面的例子中,当调用 greet 方法的时候,该方法的this值会绑定到 obj 对象。

function greet() {
  var reply = [this.animal, 'typically sleep between', this.sleepDuration].join(' ');
  console.log(reply);
}

var obj = {
  animal: 'cats', sleepDuration: '12 and 16 hours'
};

greet.call(obj);  // cats typically sleep between 12 and 16 hours
Function.prototype.apply()
  • 语法

apply(thisArg)
apply(thisArg, argsArray)

  • thisArg:在 fun 函数运行时指定的 this 值。需要注意的是,指定的 this 值并不一定是该函数执行时真正的 this 值,如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象。

  • argsArray:一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 fun 函数。如果该参数的值为null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。浏览器兼容性请参阅本文底部内容。

返回值

调用有指定 this 值和参数的函数的结果。

const numbers = [5, 6, 2, 3, 7];

const max = Math.max.apply(null, numbers);

console.log(max);
// expected output: 7

const min = Math.min.apply(null, numbers);

console.log(min);
// expected output: 2

apply 和 call 的区别
  • 其实 apply 和 call 基本类似,他们的区别只是传入的参数不同。

  • 所以 apply 和 call 的区别是 call 方法接受的是若干个参数列表,而 apply 接收的是一个包含多个参数的数组。

Function.prototype.bind()
  • bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。

语法

function.bind(thisArg[, arg1[, arg2[, …]]])

参数

thisArg

  • 调用绑定函数时作为 this 参数传递给目标函数的值。如果使用new运算符构造绑定函数,则忽略该值。当使用 bind 在 setTimeout 中创建一个函数(作为回调提供)时,作为 thisArg 传递的任何原始值都将转换为 object。如果 bind 函数的参数列表为空,或者thisArg是null或undefined,执行作用域的 this 将被视为新函数的 thisArg。

arg1, arg2, ...

  • 当目标函数被调用时,被预置入绑定函数的参数列表中的参数。

返回值

  • 返回一个原函数的拷贝,并拥有指定的 this 值和初始参数。
  var a ={
        name : "Cherry",
        fn : function (a,b) {
            console.log( a + b)
        }
    }

    var b = a.fn;
    b.bind(a,1,2)

所以我们可以看出,bind 是创建一个新的函数,我们必须要手动去调用:

    var a ={
        name : "Cherry",
        fn : function (a,b) {
            console.log( a + b)
        }
    }

    var b = a.fn;
    b.bind(a,1,2)()           // 3
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值