JavaScript基础篇(41-50题)

此文章,来源于印客学院的资料【第一部分:基础篇(105题)】,也有一些从网上查找的补充。

这里只是分享,便于学习

诸君可以根据自己实际情况,自行衡量,看看哪里需要加强。

概述如下:

  • ECMAScript6 怎么写class
  • 什么是面向对象编程及面向过程编程, 它们的异同和优缺点
  • 面向对象编程思想
  • 对web标准、可用性、可访问性的理解
  • 如何通过JS判断⼀个数组
  • 谈⼀谈javascript 中 let与var的区别
  • javascript中 map与forEach的区别
  • 谈⼀谈你理解的函数式编程
  • 谈⼀谈箭头函数与普通函数的区别?
  • 谈⼀谈函数中this的指向

ECMAScript6 怎么写class

在 ECMAScript 6(ES6)中,你可以使用 class 关键字 来定义一个类。类是一种创建对象的蓝图,它具有属性和方法。

以下是一个示例,展示了如何使用 ES6 编写一个简单的类:

class Animal {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  eat(food) {
    console.log(`${this.name} is eating ${food}.`);
  }

  sleep() {
    console.log(`${this.name} is sleeping.`);
  }

  static info() {
    console.log("This is an animal class.");
  }
}

// 创建 Animal 类的实例
const cat = new Animal("Tom", 3);

cat.eat("fish");  // 输出:Tom is eating fish.
cat.sleep();      // 输出:Tom is sleeping.

Animal.info();    // 输出:This is an animal class.

在上面的示例中,我们定义了一个名为 Animal 的类。

  • constructor 方法用于初始化对象的属性。
  • 类中的其他方法(例如 eat()sleep())定义了对象的行为。
  • static 关键字用于定义静态方法,无需实例化类即可调用。

使用 new 关键字可以创建类的实例,然后我们可以调用实例的方法。

同时,还可以直接调用静态方法,如 Animal.info()

这只是一个简单的示例,你可以根据需要在类中添加更多属性和方法。希望对你有所帮助!

什么是面向对象编程及面向过程编程, 它们的异同和优缺点

面向对象编程(Object-Oriented Programming,OOP)和面向过程编程(Procedural Programming)是两种不同的编程范式。

面向对象编程(OOP) 是一种将数据和操作数据的方法封装在一起的编程方式。

它基于 对象 的概念,通过创建类、实例化对象、定义对象之间的关系来组织和管理代码。面向对象编程强调代码的可重用性、可维护性和可扩展性。

面向过程编程(Procedural Programming) 是一种按照解决问题的步骤和过程进行编程的方式。

它将程序看作是 一系列的函数过程 ,通过顺序执行这些函数或过程来达到目标。面向过程编程强调过程的逻辑和步骤。

异同点:

  1. 封装性:面向对象编程通过将数据和相关操作封装在类中,实现了数据的隐藏和保护,只提供接口进行访问。而面向过程编程没有显式的封装机制,数据和操作分散在不同的函数中。
  2. 继承性:面向对象编程支持继承机制,可以通过继承获得父类的属性和方法,并且可以通过多态实现不同子类对同一方法的不同实现。而面向过程编程没有内置的继承机制,需要手动复制粘贴代码来实现类似的功能。
  3. 多态性:面向对象编程支持多态,即不同对象对同一消息的响应方式可以不同。而面向过程编程没有内置的多态机制。
  4. 可维护性和可扩展性:面向对象编程通过封装、继承和多态等特性,使得代码更易于维护和扩展。面向过程编程在处理大型复杂项目时,可能会导致代码冗长、难以维护。

优点:

面向对象编程的优点包括:

  • 代码可重用性:通过封装和继承,可以在不同的地方重用代码,提高开发效率。
  • 可维护性:代码结构清晰,易于理解和修改。
  • 扩展性:通过继承和多态,可以方便地添加新功能和扩展现有功能。

缺点:

面向对象编程的缺点包括:

  • 学习曲线较陡:相对于面向过程编程,面向对象编程需要掌握更多的概念和技术。
  • 性能开销:相比简单的面向过程编程,面向对象编程可能会引入额外的性能开销。
  • 面向对象设计的复杂性:良好的面向对象设计需要考虑对象之间的关系和交互,可能增加设计和开发的复杂性。

选择面向对象编程还是面向过程编程,取决于具体的需求和项目特点。对于大型、复杂的项目,面向对象编程通常更适合,它提供了更好的可维护性和扩展性。而对于小型、简单的项目,面向过程编程可能更简洁、高效。

面向对象编程思想

基本思想是使用 对象, 类, 继承, 封装等 基本概念来进⾏程序设计

面向对象编程(Object-Oriented Programming,简称OOP)是一种编程思想和方法,它将程序中的数据(对象)与操作(方法)组织在一起,通过封装、继承和多态等特性实现代码的模块化、可重用和易维护。

面向对象编程有以下几个核心概念:

  1. 类(Class):类是对象的模板,描述了对象的属性和行为。它定义了对象的结构和行为的初始状态。

  2. 对象(Object):对象是类的一个实例,拥有类定义的属性和方法。对象是程序中的基本单元,可以通过实例化类来创建。

  3. 封装(Encapsulation):封装是将数据和方法(操作)组合在一起的机制,通过访问修饰符限制对数据的访问方式。封装隐藏了对象内部的具体实现细节,只暴露必要的接口给外部使用。

  4. 继承(Inheritance):继承允许一个类派生出另一个类,并继承父类的属性和方法。通过继承,子类可以重用父类的代码,并在此基础上添加、修改或扩展功能。

  5. 多态(Polymorphism):多态是指不同类型的对象可以使用相同的接口进行操作,产生不同的结果。多态提供了代码的灵活性和可扩展性,通过方法重写和方法重载来实现。

面向对象编程的优点包括:

  • 代码重用性高、
  • 可维护性好、
  • 扩展性强、
  • 逻辑清晰等。

它使得程序员可以更加关注对象之间的交互和协作,从而提高开发效率和代码质量。在

许多编程语言中,如Java、C++和Python,面向对象编程都是主要的编程范式。

对web标准、可用性、可访问性的理解

Web标准 是指由W3C(World Wide Web Consortium)等组织制定的技术规范和最佳实践,用于确保网页在不同平台、浏览器和设备上正确解析和显示

它包括HTML、CSS、JavaScript等语言的规范,以及相关的协议和API。遵循Web标准可以提高网页的可维护性、可扩展性和跨平台兼容性。

可用性 是指网站或应用程序对用户来说易于理解、学习和操作的程度

一个具有良好可用性的网站应该满足用户的期望,提供直观的导航和布局,使得用户能够快速找到所需信息或功能。为了提高可用性,需要进行用户研究、界面设计、交互设计等工作,确保用户界面的一致性、反馈机制的清晰性和任务流程的简洁性。

可访问性 是指网站或应用程序对所有用户,包括残障人士,都具有平等的访问和使用权利

它涉及到提供无障碍的界面设计和交互方式,可以通过辅助技术如屏幕阅读器、放大器等来满足不同残障人士的需求。为了实现可访问性,需要遵循WCAG(Web Content Accessibility Guidelines)提供的指南,例如使用语义化的HTML标记、提供替代文本描述媒体内容、确保键盘导航可用等。

综上所述

  • Web标准是确保网页在不同环境下一致性和兼容性的规范;
  • 可用性关注用户体验和交互设计,提高用户满意度;
  • 可访问性保证所有用户都能够平等地访问和使用网站或应用程序。

这些方面的重视和实践可以提高产品的质量、可持续性和用户友好性。

如何通过JS判断⼀个数组

instanceof 方法 – instanceof 运算符是用来测试⼀个对象 是否在其原型链原型构造函数的属性

var arr = []; 
arr instanceof Array; // true

constructor 方法 – constructor 属性返回对创建此对象的数组函数的引用,就是返回对象相对应的构造函数

var arr = []; 
arr.constructor == Array; //true

ES5 新增方法 isArray()

var a = new Array(123); 
var b = new Date(); 
console.log(Array.isArray(a)); //true 
console.log(Array.isArray(b)); //false

谈⼀谈javascript 中 let与var的区别

在 JavaScript 中,letvar 是两种用于声明变量的关键字。

它们有以下几个主要区别:

作用域

  • 使用 let 声明的变量具有块级作用域,只在所在的代码块(大括号 {})内部有效。
  • 而使用 var 声明的变量具有函数作用域,在整个函数内部都有效。

如果在块级作用域中使用 var 声明变量,则该 变量会提升到所在函数的顶部

// 使用 let
function example() {
  let x = 10;
  if (true) {
    let x = 20; // 在块级作用域内重新定义 x
    console.log(x); // 输出 20
  }
  console.log(x); // 输出 10
}

// 使用 var
function example() {
  var x = 10;
  if (true) {
    var x = 20; // 在函数作用域内重写 x
    console.log(x); // 输出 20
  }
  console.log(x); // 输出 20
}

变量提升

  • 使用 let 声明的变量不会被提升到作用域顶部,只有在声明语句出现后才能使用变量。
  • 而使用 var 声明的变量会被提升到作用域顶部,可以在声明之前使用变量,但其值为 undefined
console.log(x); // 报错:ReferenceError: x is not defined

let x = 10;

console.log(y); // 输出 undefined

var y = 20;

重复声明:在相同作用域中,

  • 使用 let 重复声明同一个变量会导致语法错误。
  • 而使用 var 可以重复声明同一个变量,不会报错。
let x = 10;
let x = 20; // 报错:SyntaxError: Identifier 'x' has already been declared

var y = 10;
var y = 20; // 不会报错,y 的值被重新赋值为 20

总结

  • let 更加安全,具有更严格的作用域规则,避免了变量提升和重复声明的问题,推荐在需要声明变量时优先使用 let 关键字。- 而 var 则存在一些历史遗留问题,较少在现代 JavaScript 开发中使用。

javascript中 map与forEach的区别

forEach 方法, 是最基本的方法,就是遍历与循环, 默认有3个传参:分别是

  • 遍历的数组 内容 item 、
  • 数组索引 index 、
  • 当前遍历数组 Array

map 方法, 基本用法与 forEach ⼀致,但是不同的, 它会 返回⼀个新的数组,所以在 callback需要有
return 值, 如果没有,会返回 undefined

详细如下

在 JavaScript 中,mapforEach是数组的两个常用方法,

它们有一些区别:

  1. 返回值:map方法会返回一个新的数组,其中包含对原数组的每个元素执行回调函数后得到的结果。而forEach方法没有返回值,它只是对原数组的每个元素依次执行回调函数。

  2. 对原数组的影响:map方法不会改变原数组,它会返回一个新的数组。而forEach方法只是遍历数组,并对每个元素执行回调函数,不会改变原数组。

  3. 使用场景:map方法通常用于处理数组的每个元素,生成一个新的数组,例如对数组中的每个数字求平方。而forEach方法用于遍历数组,执行某些操作,但不需要生成新的数组。

示例代码:

// 使用map方法
const numbers = [1, 2, 3, 4];
const squaredNumbers = numbers.map(num => num * num);
console.log(squaredNumbers); // 输出: [1, 4, 9, 16]

// 使用forEach方法
const names = ['Alice', 'Bob', 'Charlie'];
names.forEach(name => console.log('Hello, ' + name));
// 输出:
// Hello, Alice
// Hello, Bob
// Hello, Charlie

需要注意的是,在使用mapforEach时,传递的回调函数可以接收三个参数:当前元素的值、当前索引和原数组本身。

谈⼀谈你理解的函数式编程

函数式编程是一种编程范式,它的核心思想是 计算过程视为函数的组合和变换。在函数式编程中,函数被看作是一等公民,具有不变性无副作用的特性。

简单说, “函数式编程"是⼀种"编程范式” ( programming paradigm), 也就是如何编写程序的方法论。它具有以下特性: 闭包高阶函数惰性计算递归函数是"第⼀等公民"、只用"表达式

函数式编程强调使用 纯函数 进行计算,即 函数的输出仅由输入决定没有任何可观察的副作用 。这种不变性使得函数易于推理、测试和并发处理。纯函数避免了依赖于外部状态的复杂性,使得程序更加可靠和可维护。

另一个重要的概念是 不可变性,即数据一旦创建就不能被修改。在函数式编程中,函数不会改变传入的参数或任何可变状态,而是通过创建新的数据副本来表示状态的变化。因此,函数式编程支持高度可扩展和可并行化的设计。

函数式编程还倡导使用 高阶函数,即函数可以作为参数传递给其他函数或作为结果返回。这种方式使得代码更加简洁和可复用。常见的高阶函数操作包括映射、过滤和归约等,它们可以通过组合来解决复杂的问题。

递归 是函数式编程的重要特性之一。函数式编程鼓励使用递归来解决问题,因为递归可以通过函数调用自身来简洁地表达重复的计算逻辑。递归可以处理复杂的数据结构和算法,但需要注意递归深度和性能问题。

惰性求值 也是函数式编程中常用的技术。惰性求值意味着只在需要时才计算表达式的值,这样可以避免不必要的计算,并提高程序的性能和效率。

总而言之,函数式编程是一种将计算过程看作函数组合和变换的编程范式。它强调纯函数、不可变性、高阶函数、递归和惰性求值等概念。函数式编程的优点包括代码简洁、可复用、易于推理和并行处理等。

JavaScript中函数式编程的一些示例:

  1. 映射(Map):使用Array.map()方法将一个函数应用于数组中的每个元素,并返回结果数组。
const numbers = [1, 2, 3, 4, 5];
const squaredNumbers = numbers.map(x => x ** 2);
// 输出:[1, 4, 9, 16, 25]
  1. 过滤(Filter):使用Array.filter()方法根据特定条件过滤数组中的元素,并返回满足条件的元素组成的新数组。
const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter(x => x % 2 === 0);
// 输出:[2, 4]
  1. 归约(Reduce):使用Array.reduce()方法对数组中的元素进行累积操作,得到一个单一的结果。
const numbers = [1, 2, 3, 4, 5];
const sumOfNumbers = numbers.reduce((x, y) => x + y);
// 输出:15
  1. 高阶函数:在JavaScript中,函数是作为一等公民,可以将其作为参数传递给其他函数或从函数中返回函数。
function multiplyBy(n) {
  return function(x) {
    return x * n;
  };
}

const double = multiplyBy(2);
const result = double(5);
// 输出:10
  1. 递归:在JavaScript中,函数可以通过调用自身来实现递归。
function factorial(n) {
  if (n === 0) {
    return 1;
  } else {
    return n * factorial(n - 1);
  }
}

const result = factorial(5);
// 输出:120

以上示例展示了JavaScript中函数式编程的一些常见操作和概念。函数式编程可以提供更简洁、可读性强的代码,并且能够通过组合和抽象来解决复杂的问题。函数式编程在JavaScript中得到了广泛的应用,特别是在处理数组和进行异步操作时更加方便和灵活。

谈⼀谈箭头函数与普通函数的区别?

箭头函数和普通函数在语法和功能上有以下区别:

  1. 语法简洁性:箭头函数提供了更简洁的语法形式。它使用箭头(=>)来定义函数,省略了function关键字和大括号({})的使用。对于单个表达式的函数体,可以省略return关键字。

普通函数示例:

function multiply(x, y) {
  return x * y;
}

箭头函数示例:

const multiply = (x, y) => x * y;
  1. this 的指向:箭头函数没有自己的this绑定,它会捕获并使用周围上下文中的this值。这意味着在箭头函数中,this的值是定义函数时所在的上下文的this,而不是在运行时绑定的。

普通函数示例:

const obj = {
  name: 'Alice',
  sayHello: function() {
    console.log('Hello, ' + this.name);
  }
};
obj.sayHello(); // 输出:Hello, Alice

箭头函数示例:

const obj = {
  name: 'Alice',
  sayHello: function() {
    const greet = () => {
      console.log('Hello, ' + this.name);
    };
    greet();
  }
};
obj.sayHello(); // 输出:Hello, Alice
  1. arguments 对象:箭头函数没有自己的arguments对象,它会捕获并使用周围上下文中的arguments。这意味着在箭头函数中,无法通过arguments获取传入的参数列表,而是要使用剩余参数(rest parameters)来处理参数。

普通函数示例:

function sum() {
  let total = 0;
  for (let i = 0; i < arguments.length; i++) {
    total += arguments[i];
  }
  return total;
}
sum(1, 2, 3); // 输出:6

箭头函数示例:

const sum = (...numbers) => {
  let total = 0;
  for (let i = 0; i < numbers.length; i++) {
    total += numbers[i];
  }
  return total;
};
sum(1, 2, 3); // 输出:6

综上所述,箭头函数在语法上更简洁,没有自己的thisarguments,而是从周围上下文中继承这些值。因此,在选择使用箭头函数还是普通函数时,需要考虑具体的上下文和功能需求。普通函数在需要动态的thisarguments的情况下更合适,而箭头函数适用于简单的函数和对this不依赖于上下文的情况。

谈⼀谈函数中this的指向

函数中的this关键字指向当前执行函数的上下文对象。具体的指向取决于函数的调用方式和函数类型。

this的指向在函数定义的时候是确定不了的, 只有函数执⾏的时候才能确定this到底指向谁, 实际上this的最终指向的是那个调用它的对象

下面介绍几种常见情况:

  1. 全局作用域下的函数调用:当函数在全局作用域下调用时,this指向全局对象(浏览器环境下通常是window对象,Node.js环境下是global对象)。
function test() {
  console.log(this);
}
test(); // 浏览器环境输出:Window { ... },Node.js环境输出:Object [global] { ... }
  1. 对象方法调用:当函数作为对象的方法调用时,this指向该对象。
const obj = {
  name: 'Alice',
  getName() {
    console.log(this.name);
  }
};
obj.getName(); // 输出:Alice
  1. 构造函数调用:当函数用作构造函数调用时,this指向新创建的实例对象。
function Person(name) {
  this.name = name;
}
const person = new Person('Alice');
console.log(person.name); // 输出:Alice
  1. 使用call、apply或bind改变this:可以使用callapplybind方法显式地改变函数中this的指向。
function test() {
  console.log(this.name);
}

const obj1 = {
  name: 'Alice'
};

const obj2 = {
  name: 'Bob'
};

test.call(obj1); // 输出:Alice
test.apply(obj2); // 输出:Bob

const boundTest = test.bind(obj1);
boundTest(); // 输出:Alice
  1. 箭头函数内部的this:箭头函数没有自己的this,它会继承外层作用域的this值。
const obj = {
  name: 'Alice',
  getName: () => {
    console.log(this.name);
  }
};
obj.getName(); // 输出:undefined

总结来说,函数中的this指向是动态确定的,取决于函数的调用方式和函数类型。需要根据具体情况来理解和使用this关键字。

你可能感兴趣的:(前端杂货铺,javascript,开发语言,ecmascript)