JS 函数进阶

函数

函数定义构成

1.函数名称标识符。
函数名称是函数声明语句的必须部分。
2.一对圆括号。
包含0个或多个由逗号隔开的标识符,这些为函数的形参。
3.一对花括号。
其中包含0条或多条JavaScript语句。这些语句构成了函数体:一旦调用函数,就会执行这些语句。
函数只会执行到函数体中的return语句处,其后面的语句不再执行。

函数定义方式

1.函数声明语法
function add(num1, num2) {
  			return num1 + num2;
}
2.函数表达式
let sub = function (num1, num2) {
  	return num1 - num2;
}

若使用函数表达式创建的函数,函数标识符只能在该函数的作用域内使用,因此若使用函数标识符调用函数,则会报错:该函数标识符未被定义。若在函数内部输出该函数标识符,则会返回该函数代码。
※ 函数声明与函数表达式的区别
函数声明会将函数提升,函数表达式不能将函数提升,提升的是变量,因此,若用函数表达式定义函数时,要先定义才能调用。

3.箭头函数
let mul = (mun1, num2) => num1 * num2;
let mul = (mun1, num2) => {
  			return num1 * num2;
};
// 当函数体只有一句return语句时,可以省略花括号。

let f1 = () => {
  	console.log("arrow function");
};
let f2 = x => x ** 2;
// 当函数有多个形参时,要用圆括号将其括起来。
let xx = ((x) => x ** x)(4);
// 箭头函数也可以立即调用,先将圆括号将函数括起来,后面在跟一个圆括号将实参进行传递。
4.Function构造函数

这个构造函数接收任意多个字符串参数,最后一个参数始终会被当成函数体,而之前的参数都是新函数的参数。

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

※ 不推荐使用这种语法来定义函数,因为这段代码会被解释两次:第一次是将它当作常规ECMAScript 代码,第二次是解释传给构造函数的字符串。这显然会影响性能。

Arguments对象

一个类数组对象(但不是 Array 的实例),因此可以使用中括号语法访问其中的元素。
要确定接收到的参数个数,可以访问 arguments.length 属性。

  1. 函数表达式内部支持arguments 对象,而箭头函数内部不支持arguments对象。
  2. Arguments包含剩余参数,若剩余参数没有接受,则是一个空数组。

参数默认值

Es6中增加了参数默认值,可以在定义函数的时候对形参进行默认值的赋值,当没有实参进行传递或者传递的实参类型为undefined或实参是undefined时,该参数则将为默认值。

function f2(name = "User", age = 0) {
  	console.log(name, age);
}

扩展参数

function sum() {
  let r = 0;
  for (let i = 0; i < arguments.length; i++) {
    r += arguments[i];}
  return r;
}
let nums = [1, 2, 3, 4, 5];
// 如果要把nums当做实参传到sum()时,则要用到扩展运算符
console.log(sum(...nums));
// 此时就能把nums中所有的元素传入到函数中。

剩余参数

function sum2(name, ...scores) {
    let r = scores.reduce((x, y) => x + y, 0);
    console.log(`${name}总分为:${r}`);
};
sum2("Tom", 80, 90, 100); // Tom总分为:270。

剩余参数会将实参中剩余的参数全部传入到函数中,且剩余参数只能位于参数列表的末尾。
※ 扩展参数位于函数的实参位置,而剩余参数则位于函数的形参位置。

函数调用

构成函数主体的JavaScript代码在定义之时并不会执行,只有调用该函数时,它们才会执行。

有4种方式来调用JavaScript函数:

  1. 作为函数
  2. 作为方法
  3. 作为构造函数
  4. 通过它们的call()和apply()方法间接调用
方法调用
方法是属于某个特定对象才能调用的函数。
调用上下文

1.关键字this没有作用域的限制,嵌套的函数不会从调用它的函数中继承this。
2.This是通过计算得出来的,每个作用域有不同的this

间接调用

使用函数对象的call( )和apply( )方法可以间接调用函数。
第一个参数指定调用上下文(函数内部的this),第二个参数给函数传递参数。

回调函数

被作为实参传入另一函数,并在该外部函数内被调用,用以来完成某些任务的函数,称为回调函数。

函数属性

length属性

1.在函数体里,arguments.length表示传入函数的实参的个数。
2.而函数本身的length属性是只读的,它代表函数声明的实际参数的数量。

prototype属性

每一个函数都包含一个prototype属性,这个属性是指向一个对象的引用,这个对象称做“原型对象”(prototype object)。
每一个函数都包含不同的原型对象。当将函数用做构造函数的时候,新创建的对象会从原型对象上继承属性。

函数方法

call( )和apply( )方法

通过调用方法的形式来间接调用函数。
call()和apply()的第一个实参是要调用函数的主体对象,它是调用上下文,在函数体内通过this来获得对它的引用。

bind( )方法
  1. 将函数绑定至某个对象,且可以绑定参数值。
  2. 当在函数f()上调用bind()方法并传入一个对象o作为参数,这个方法将返回一个新的函数。
  3. (以函数调用的方式)调用新的函数将会把原始的函数f()当做o的方法来调用。 传入新函数的任何实参都将传入原始函数。
  4. 通过bind()为函数绑定调用上下文后,返回的函数不能通过call和apply修改调用上下文对象。

示例1:

let obj = {
  x: 10,
  show: function (y) {
    let r = "";
    for (let i = 0; i < y; i++) {
      r += this.x + " ";
    }
    console.log(r);
  },
};
obj.show(4); // 10 10 10 10 

let ss = obj.show.bind({ x: 1000 });
ss(3); // 1000 1000 1000

let sum = function (x, y) {
  return x + y;
};
let succ = sum.bind(null, 1);
console.log(succ(2)); // 3

let obj = {};
obj.supAdd = sum.bind(obj, 10); 
/* ƒ (x, y) {
 * return x + y;}
 */

//偏函数,固定一个函数的一个或者多个参数,返回一个新的函数,这个函数用于接受剩余的参数。
console.log(obj.supAdd(20)); // 30

偏函数的好处:

  1. 通过创建一个名称易懂的独立函数,调用是无需每次传入第一个参数,因为第一个参数通过bind提供了固定值。
  2. 当我们有一个很通用的函数,为了方便提供一个较常用的变体。

示例2:

let obj = { z: 1000 };

function sum(x, y) {
    let r = x + y;
    if (Object.getPrototypeOf(this) != global /*window*/ ) {
        console.log(this);
        r += this.z;
    };
    return r;
};
obj.sum = sum;
console.log(obj.sum(20, 30)); // 1050
console.log(obj.sum.call({ z: 1 }, 2, 3)); // 6
// 当函数没有用bind方法进行绑定时,可以通过call方法对调用上下文对象进行修改

obj.sum = sum.bind(obj);
console.log(obj.sum(100, 200)); // 1300
console.log(obj.sum.apply({ z: 1 }, [50, 60])); // 1110
// 当函数用bind方法绑定后,apply方法将不能修改调用上下文的属性值

函数闭包

JavaScript采用词法作用域(lexical scoping)。

  1. 函数的执行依赖于变量作用域,这个作用域是在函数定义时决定的,而不是函数调用时决定的。
  2. 为了实现这种词法作用域,JavaScript函数对象的内部状态不仅包含函数的代码逻辑,还必须引用当前的作用域链


函数对象可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内,这种特性在计算机科学文献中称为“闭包(closure)”。

  1. 从技术的角度讲,所有的JavaScript函数都是闭包:它们都是对象,它们都关联到作用域链。
var  scope  =  "globle scope";

function  checkscope()  {  
    var  scope  =  "local scope";  
    function  f()  {     return  scope;   }  
    return  f();
}
console.log(checkscope()); // local scope
var  scope  =  "globle scope";

function  checkscope()  {  
    var  scope  =  "local scope";  
    function  f()  {     return  scope;   }  
    return  f;
}
var  ff  =  checkscope();
console.log(ff()); // local scope

它们可以捕捉到局部变量(和参数),并一直保存下来,看起来像这些变量绑定到了在其中定义它们的外部函数。

闭包原理

  1. 在JavaScript中,如果一个对象不再被引用,那么这个对象就会被垃圾回收机制回收。
  2. 每次调用JavaScript函数的时候,都会为之创建一个新的对象(活动对象Activation
    Object)用来保存局部变量,把这个对象添加至作用域链中。
  3. 当函数返回的时候,就从作用域链中将这个绑定变量的对象删除。
    1. 如果不存在嵌套的函数,也没有其他引用指向这个绑定对象,它就会被当做垃圾回收掉。
    2. 如果定义了嵌套的函数,每个嵌套的函数都各自对应一个作用域链,并且这个作用域链指向一个变量绑定对象。
  4. 如果这个函数定义了嵌套的函数,并将它作为返回值返回或者存储在某处的属性里,这时就会有一个外部引用指向这个嵌套的函数。
    1. 它就不会被当做垃圾回收,并且它所指向的变量绑定对象也不会被当做垃圾回收。
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: JavaScript核心进阶:阳波PDF是一本面向已经掌握基础JavaScript知识的读者而设计的进阶书籍。此书主要内容涵盖了JavaScript核心的高级特性和使用技巧,旨在帮助读者更深入地理解JavaScript并提升自己的编程能力。 首先,该书的作者是阳波老师,他在JavaScript领域有丰富的经验和深厚的理论基础。他通过清晰、详细的讲解及代码实例,帮助读者逐步了解和掌握JavaScript中的高级概念,如闭包、原型链、作用域等。 除了核心概念,该书还介绍了一些实用技巧和最佳实践,例如模块化开发、异步编程、优化性能等。这些技巧可以帮助读者更高效地编写JavaScript代码,提升应用的质量和响应速度。 此外,书中还包含了一些实战案例,通过具体的项目实例,读者能够学习到如何将JavaScript应用于实际项目中,发挥其强大的功能和灵活性。 总之,JavaScript核心进阶:阳波PDF是一本帮助已经掌握基础JavaScript知识的人提升自己的必备读物。读者能够通过阅读本书,进一步拓展对JavaScript的理解,掌握高级特性和实用技巧,并将其应用于实际项目中,从而提升编程能力和项目质量。 ### 回答2: JavaScript是一种广泛应用于Web开发的编程语言,对于想要深入了解该语言的开发者来说,掌握其核心进阶知识是至关重要的。而《JavaScript核心进阶》是一本由阳波编写的PDF电子书,该书的内容涵盖了JavaScript的核心进阶知识。 《JavaScript核心进阶》这本书包含了丰富的内容,主要分为了四个部分。第一部分介绍了Javascript的基础知识,包括变量、数据类型、运算符、表达式等。第二部分涵盖了Javascript函数和作用域,其中讲解了函数的定义、调用、参数、闭包等概念。第三部分讲解了Javascript的对象、原型和继承,重点介绍了原型链的概念和使用方法。第四部分介绍了一些高级主题,如模块化编程、异步编程、错误处理等。此外,该书还包含了许多实例和练习,帮助读者加深理解和巩固知识。 在阅读《JavaScript核心进阶》这本书后,读者将能够更好地理解JavaScript的核心概念和技巧。他们将学会如何使用适当的语法和设计模式来编写更加高效和可维护的代码。同时,这本书还帮助读者扩展了对JavaScript的应用范围,使他们能够处理更加复杂和高级的开发任务。 总而言之,《JavaScript核心进阶》是一本适合有一定JavaScript基础的开发者进行学习的书籍。它提供了大量的案例和实践,帮助读者深入理解JavaScript的核心知识。通过阅读这本书,读者将能够掌握JavaScript的核心进阶知识,提升自己的编程技能,实现更加高效和可靠的Web开发。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值