2. 第二部分:javascript高级函数和对象

news/2024/11/17 8:33:53/

2.1 函数进阶
2.1.1 高阶函数
JavaScript 中的高阶函数是指可以接受一个或多个函数作为参数,并/或者返回一个函数的函数。这种函数可以用来实现许多有用的编程模式,如函数式编程和回调函数。

以下是一些常见的 JavaScript 高阶函数示例:

  1. map()函数:接受一个函数作为参数,并将该函数应用于数组的每个元素,并返回一个新的经过函数处理的数组。
const numbers = [1, 2, 3, 4, 5];
const squaredNumbers = numbers.map(function (num) {return num * num;
});
console.log(squaredNumbers); // 输出:[1, 4, 9, 16, 25]
  1. filter()函数:接受一个函数作为参数,并使用该函数对数组进行筛选,返回一个包含满足条件的元素的新数组。
const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter(function (num) {return num % 2 === 0;
});
console.log(evenNumbers); // 输出:[2, 4]
  1. reduce()函数:接受一个函数作为参数,并使用该函数将数组的元素归约为单个值。
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce(function (acc, num) {return acc + num;
}, 0);
console.log(sum); // 输出:15
  1. forEach()函数:接受一个函数作为参数,并对数组的每个元素执行该函数。
const numbers = [1, 2, 3, 4, 5];
numbers.forEach(function (num) {console.log(num);
});
// 输出:
// 1
// 2
// 3
// 4
// 5

这些只是高阶函数的一些示例,JavaScript 中还有许多其他的高阶函数,如sort()every()some()等,它们都能提供更多的功能和灵活性,以便在 JavaScript 中实现复杂的逻辑和算法。
2.1.2 闭包和作用域链
闭包(Closure)和作用域链(Scope Chain)是 JavaScript 中重要的概念,它们密切相关并经常一起讨论。

作用域(Scope)是指变量、函数和对象的可访问范围。在 JavaScript 中,每个函数都会创建一个新的作用域。作用域链是指在函数嵌套的情况下,内部函数可以访问外部函数的变量和函数,形成一个作用域的链条。

闭包是指在函数内部创建的函数,并且可以访问其外部函数的变量和作用域,即使外部函数已经执行完毕,闭包仍然保留对外部函数作用域的引用。闭包使得函数可以记住并访问在其词法作用域之外的变量。

下面是一个示例来说明闭包和作用域链的概念:

function outerFunction() {var outerVariable = "I am outside!";function innerFunction() {console.log(outerVariable); // 内部函数可以访问外部函数的变量}return innerFunction;
}var myFunction = outerFunction();
myFunction(); // 输出:'I am outside!'

在上面的例子中,innerFunction是在outerFunction内部定义的,并且可以访问outerFunction的变量outerVariable。尽管outerFunction已经执行完毕,但通过返回innerFunction,我们创建了一个闭包,innerFunction仍然可以访问和引用外部作用域中的变量。

作用域链是由函数的定义位置和调用位置共同决定的。当访问变量时,JavaScript 引擎首先在当前作用域中查找,如果找不到,则继续沿着作用域链向上查找,直到找到变量或到达全局作用域。这种机制保证了内部函数可以访问外部函数的变量。

闭包和作用域链在 JavaScript 中具有广泛的应用,可以用于封装私有变量、实现模块化、处理异步操作等场景。但同时需要注意避免内存泄漏,因为闭包会持有外部作用域的引用,导致外部作用域中的变量无法被垃圾回收。
2.1.3 函数式编程
函数式编程是一种编程范式,它将计算视为函数应用的连续转换和组合,强调使用纯函数和避免可变状态和副作用。在 JavaScript 中,函数式编程可以通过以下几个方面来实现:

  1. 纯函数(Pure Functions):纯函数是指在相同的输入下,总是产生相同的输出,并且没有副作用的函数。它们不依赖于外部状态,也不修改外部状态。纯函数对于给定的输入只关心输出,不产生额外的影响。
function square(x) {return x * x;
}const result = square(5); // 纯函数调用
  1. 不可变数据(Immutable Data):在函数式编程中,数据是不可变的,即一旦创建,就不能修改。当需要修改数据时,实际上是创建一个新的数据副本,并在副本上进行操作。这有助于避免意外的副作用和数据竞争。
const numbers = [1, 2, 3, 4, 5];
const doubledNumbers = numbers.map((num) => num * 2); // 创建新的数组副本
  1. 高阶函数(Higher-order Functions):高阶函数是指可以接受一个或多个函数作为参数,并/或者返回一个函数的函数。它们可以用来组合和转换函数,使代码更具表现力和可重用性。
function multiplyBy(factor) {return function (x) {return x * factor;};
}const triple = multiplyBy(3); // 返回一个函数
const result = triple(5); // 调用返回的函数
  1. 函数组合(Function Composition):函数组合是将多个函数组合成一个新的函数的过程。可以使用函数组合运算符(如composepipe)将多个函数按特定顺序组合起来,形成一个新的函数。
const add = (x) => x + 1;
const multiply = (x) => x * 2;const combined = compose(multiply, add); // 组合函数
const result = combined(3); // 调用组合后的函数
  1. 延迟执行(Lazy Evaluation):函数式编程鼓励延迟执行,即在需要时才计算结果。这可以通过使用惰性计算、生成器、迭代器等技术来实现,以避免不必要的计算。
function* generateNumbers() {let i = 0;while (true) {yield i++;}
}const numbers = generateNumbers(); // 创建生成器
const result = numbers.next().value; // 惰性计算,只计算下一个值

函数式编程提供了一种声明式的编程风格,强调代码的可读性、可维护性和可测试性。它可以使代码更加模块化、可组合和

易于推理。在 JavaScript 中,许多库(如 Lodash、Ramda)提供了丰富的函数式编程工具和函数,可以更方便地编写函数式风格的代码。
2.2 对象和原型
2.2.1 对象创建和构造函数
在 JavaScript 中,对象可以通过多种方式进行创建。以下是两种常见的方式:字面量对象创建和构造函数创建。

  1. 字面量对象创建:
    使用字面量语法直接创建对象,可以在大括号 {} 内指定对象的属性和方法。
// 创建一个空对象
const obj = {};// 创建带有属性和方法的对象
const person = {name: "John",age: 30,greet: function () {console.log("Hello!");},
};
  1. 构造函数创建:
    使用构造函数创建对象,构造函数是一个普通的函数,通过 new 关键字调用,并在函数内部使用 this 关键字引用新创建的对象。
// 创建一个构造函数
function Person(name, age) {this.name = name;this.age = age;this.greet = function () {console.log("Hello!");};
}// 使用构造函数创建对象
const person = new Person("John", 30);

在上面的示例中,Person 是一个构造函数,通过 new 关键字创建了一个 Person 类型的对象,并传递了相应的参数。构造函数内部使用 this 关键字来引用新创建的对象,并设置对象的属性和方法。

使用构造函数创建的对象具有相同的属性和方法,因此它们共享相同的原型。可以通过在构造函数的原型对象上定义属性和方法,实现对象之间的共享和原型继承。

// 在构造函数原型上定义方法
Person.prototype.introduce = function () {console.log(`My name is ${this.name} and I'm ${this.age} years old.`);
};// 调用构造函数原型上的方法
person.introduce(); // 输出:My name is John and I'm 30 years old.

通过使用构造函数和原型,可以实现更好的代码复用和扩展性,使对象拥有共享的属性和方法,同时每个对象也可以具有自己的属性和方法。
2.2.2 原型和原型链
在 JavaScript 中,每个对象都有一个原型(prototype),并且原型之间可以形成一个原型链(prototype chain)。原型链是 JavaScript 实现继承的机制之一。

  1. 原型(prototype):
  • 每个 JavaScript 对象都有一个原型,它可以是另一个对象或 null。
  • 对象的原型可以通过 __proto__ 属性访问(不推荐使用)或使用 Object.getPrototypeOf(obj) 方法获取。
  • 原型是对象共享属性和方法的存储位置,当对象访问属性或方法时,如果对象本身没有该属性或方法,它会沿着原型链向上查找。
  1. 原型链(prototype chain):
  • 原型链是由对象的原型构成的链条,每个对象都有一个指向其原型的链接。
  • 当对象访问属性或方法时,如果对象本身没有该属性或方法,它会沿着原型链向上查找,直到找到该属性或方法或到达原型链的末端(null)。
  • 原型链的顶端是 Object.prototype,它是大多数对象的最终原型。

以下是一个示例,说明原型和原型链的概念:

// 定义一个构造函数
function Person(name) {this.name = name;
}// 在构造函数原型上定义方法
Person.prototype.greet = function () {console.log(`Hello, my name is ${this.name}.`);
};// 创建对象实例
const person = new Person("John");// 访问对象属性
console.log(person.name); // 输出:John// 访问对象方法
person.greet(); // 输出:Hello, my name is John.// 通过原型链访问对象方法
console.log(person.toString()); // 输出:[object Object]

在上面的例子中,person 对象实例通过原型链继承了 Object.prototype 上的 toString 方法。当对象本身没有 toString 方法时,它会沿着原型链向上查找并调用继承的 toString 方法。

原型链的概念使得 JavaScript 中的对象可以实现继承和共享属性与方法的特性。通过在构造函数的原型上定义属性和方法,可以使所有通过该构造函数创建的对象共享这些属性和方法。同时,原型链也提供了一种方式,让对象在没有某个属性或方法时,能够查找并使用它们。
2.2.3 ES6 中的类和继承
在 ECMAScript 6(ES6)中引入了类(class)和继承的语法糖,使得在 JavaScript 中实现面向对象编程更加直观和易用。

类(Class)是一种用于创建对象的模板或蓝图,它定义了对象的属性和方法。可以通过关键字 class 声明一个类,并使用 constructor 方法定义构造函数。

以下是一个示例展示如何使用类创建对象:

class Person {constructor(name) {this.name = name;}greet() {console.log(`Hello, my name is ${this.name}.`);}
}const person = new Person("John");
person.greet(); // 输出:Hello, my name is John.

在上面的例子中,Person 类定义了一个构造函数 constructor 和一个方法 greet。通过 new 关键字可以创建 Person 类的对象实例,并调用该对象的方法。

继承(Inheritance)允许一个类继承另一个类的属性和方法,并且可以在此基础上进行扩展。在 ES6 中,可以使用关键字 extends 来实现类的继承。

以下是一个示例展示如何在 ES6 中实现类的继承:

class Animal {constructor(name) {this.name = name;}eat() {console.log(`${this.name} is eating.`);}
}class Dog extends Animal {bark() {console.log(`${this.name} is barking.`);}
}const dog = new Dog("Max");
dog.eat(); // 输出:Max is eating.
dog.bark(); // 输出:Max is barking.

在上面的例子中,Dog 类继承了 Animal 类,通过 extends 关键字指定了父类。子类可以访问父类的属性和方法,并可以在子类中定义自己的属性和方法。

类和继承提供了一种更直观、更清晰的方式来实现面向对象编程,使得代码更易读、易扩展和易维护。它们在 JavaScript 中成为了一种常见的编程范式,尤其在构建大型应用程序时非常有用。


http://www.ppmy.cn/news/440056.html

相关文章

德国使用花油(菜籽油、花生油)代替汽油

德国使用花油(菜籽油、花生油)代替汽油

MRC1200AZ-MO1大排量液压马达

特点: 低噪声由于偏心曲轴和five-piston振动频率低; 稳步非常低的速度下旋转由于高起动转矩、高稳定性好; 可逆旋转和输出轴能承受一定的外力径向和轴向; 分配器阀也是压力平衡和自我补偿; 消除任何连杆和其他部件,结构大大简化; 高机械效率和容积效率使用偏心轴、油缸和…

MRCN600-T1合资低速液压马达

壳体管道必须用1/2"或3/8"的管道直接与油箱连接(不带滤油器),不能太长,也不能有多余的弯曲及颈缩。马达壳体的内部压力不能超过5bar,防止损坏偏心轴上的密封件。壳体管道必须按照下列说明来连接: 水平安装:…

大泽动力30kw静音柴油发电机TO32000ET 颜色可选择

大泽动力30kw静音柴油发电机TO32000ET 颜色可选择 大泽动力30kw静音柴油发电机TO32000ET 颜色可选择 大泽动力30kw静音柴油发电机TO32000ET 颜色可选择 大泽动力30kw静音柴油发电机TO32000ET 颜色可选择 大泽动力30kw静音柴油发电机TO32000ET 颜色可选择 一、发电机组行成本低…

数控CNC加工中心采用滚珠导轨和滚柱导轨?有哪些区别?

数控CNC加工中心按照导轨区分,可分为硬轨和线轨,其中线轨加工中心常用的导轨就是滚珠导轨和滚柱导轨这两种,别看这两者只有一字之差,但区别真的很大,所以我们在购买CNC加工中心时一定要确认好是滚珠导轨还是滚柱导轨。…

家用切鸡块的机器人_好的整鸡斩块机

牛羊肉切片机在安装中需要注意的事项:1、牛羊肉切片机的刀刃长短常锋利的,所以需要先安装护刀罩。2、刀具固定螺丝只需顺时针旋转可取下。3、松开牛羊肉切片机切片刀的倾斜角度调整扳手。4、移动刀片倾斜角度整调扳手,调节切刀片后角到所需位…

螺旋榨油机的工作原理是怎样的

(1)螺旋榨油机的工作原理取油的一般过程概括的说,是由于旋转着的螺旋轴在榨膛内的推进作用,使榨膛空间体积不断缩小而对榨料产生连续的压榨作用。 压榨取油的基本过程一般分为三个阶段:进料预压(低压&#…

反重力铸造工艺中的高精度快速压力调节解决方案

摘要:针对客户调压铸造炉对真空压力控制系统的技术要求,本文介绍了相应的解决方案和验证试验。方案的技术核心是基于高速动态平衡法,采用大流量压力控制装置,与传感器和真空压力控制器组成PID闭环控制回路,其特点是可快…