编辑
2023-07-16
JS基础
00
请注意,本文编写于 506 天前,最后修改于 506 天前,其中某些信息可能已经过时。

目录

语法
this指向
arguments对象
构造函数
原型链
总结

JavaScript中有两种常见的函数定义方式:箭头函数和普通函数。它们有什么区别呢?本文将从语法、this指向、arguments对象、构造函数和原型链等方面进行比较,帮助你理解箭头函数的优势和适用场景,让你的代码更简洁、高效和易维护。

JavaScript中有两种常见的函数定义方式:箭头函数和普通函数。它们有什么区别呢?本文将从以下几个方面进行比较:

  • 语法
  • this指向
  • arguments对象
  • 构造函数
  • 原型链

语法

箭头函数的语法比普通函数更简洁,不需要使用function关键字,也不需要指定函数名(除非赋值给一个变量)。箭头函数的参数和返回值用=>符号连接,如果只有一个参数,可以省略括号;如果只有一个返回值,可以省略花括号和return关键字。例如:

js
// 普通函数 function add(a, b) { return a + b; } // 箭头函数 let add = (a, b) => a + b;

this指向

普通函数的this指向取决于调用时的上下文,可能是全局对象、某个对象、或者undefined(在严格模式下)。箭头函数的this指向则是固定的,它继承自定义时的外层作用域。这样可以避免一些常见的this指向问题,例如:

js
// 普通函数 let obj = { name: "Alice", sayHi: function () { setTimeout(function () { console.log("Hi, I'm " + this.name); // this指向全局对象,输出undefined }, 1000); }, }; obj.sayHi(); // 箭头函数 let obj = { name: "Alice", sayHi: function () { setTimeout(() => { console.log("Hi, I'm " + this.name); // this指向obj,输出Alice }, 1000); }, }; obj.sayHi();

arguments对象

普通函数内部可以访问一个特殊的变量arguments,它是一个类数组对象,包含了传入函数的所有参数。箭头函数则没有这个变量,如果需要使用参数,必须显式地定义。例如:

js
// 普通函数 function sum() { let result = 0; for (let i = 0; i < arguments.length; i++) { result += arguments[i]; } return result; } console.log(sum(1, 2, 3)); // 输出6 // 箭头函数 let sum = (...args) => { let result = 0; for (let i = 0; i < args.length; i++) { result += args[i]; } return result; }; console.log(sum(1, 2, 3)); // 输出6

构造函数

普通函数可以通过new关键字来创建实例对象,这时函数内部的this指向新创建的对象,并且返回该对象。箭头函数则不能作为构造函数,如果尝试使用new关键字,会抛出错误。例如:

js
// 普通函数 function Person(name, age) { this.name = name; this.age = age; } let alice = new Person("Alice", 18); console.log(alice); // 输出Person { name: 'Alice', age: 18 } // 箭头函数 let Person = (name, age) => { this.name = name; this.age = age; }; let alice = new Person("Alice", 18); // 抛出TypeError: Person is not a constructor

原型链

由于普通函数可以作为构造函数,它们有一个prototype属性,指向一个原型对象,该对象包含了所有实例对象共享的属性和方法。箭头函数则没有prototype属性,也不能通过原型链来实现继承。例如:

js
// 普通函数 function Animal(name) { this.name = name; } Animal.prototype.sayName = function () { console.log("My name is " + this.name); }; function Dog(name, breed) { Animal.call(this, name); // 调用父类构造函数 this.breed = breed; } Dog.prototype = Object.create(Animal.prototype); // 继承父类原型 Dog.prototype.constructor = Dog; // 修正构造函数指向 Dog.prototype.sayBreed = function () { console.log("My breed is " + this.breed); }; let dog = new Dog("Bob", "Labrador"); dog.sayName(); // 输出My name is Bob dog.sayBreed(); // 输出My breed is Labrador // 箭头函数 let Animal = (name) => { this.name = name; }; Animal.prototype.sayName = () => { console.log("My name is " + this.name); }; let Dog = (name, breed) => { Animal.call(this, name); // 调用父类构造函数 this.breed = breed; }; Dog.prototype = Object.create(Animal.prototype); // 继承父类原型 Dog.prototype.constructor = Dog; // 修正构造函数指向 Dog.prototype.sayBreed = () => { console.log("My breed is " + this.breed); }; let dog = new Dog("Bob", "Labrador"); // 抛出TypeError: Dog is not a constructor // 普通函数 function Animal(name) { this.name = name; } Animal.prototype.sayName = function () { console.log("My name is " + this.name); }; function Dog(name, breed) { Animal.call(this, name); // 调用父类构造函数 this.breed = breed; } Dog.prototype = Object.create(Animal.prototype); // 继承父类原型 Dog.prototype.constructor = Dog; // 修正构造函数指向 Dog.prototype.sayBreed = function () { console.log("My breed is " + this.breed); }; let dog = new Dog("Bob", "Labrador"); dog.sayName(); // 输出My name is Bob dog.sayBreed(); // 输出My breed is Labrador // 箭头函数 let Animal = (name) => { this.name = name; }; Animal.prototype.sayName = () => { console.log("My name is " + this.name); }; let Dog = (name, breed) => { Animal.call(this, name); // 调用父类构造函数 this.breed = breed; }; Dog.prototype = Object.create(Animal.prototype); // 继承父类原型 Dog.prototype.constructor = Dog; // 修正构造函数指向 Dog.prototype.sayBreed = () => { console.log("My breed is " + this.breed); }; let dog = new Dog("Bob", "Labrador"); // 抛出TypeError: Dog is not a constructor

总结

箭头函数和普通函数的区别主要在于语法、this指向、arguments对象、构造函数和原型链。箭头函数更适合于简单的、无状态的、不需要继承的场景,而普通函数更适合于复杂的、有状态的、需要继承的场景。在使用时,应根据具体的需求和场景来选择合适的函数定义方式。

如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:CreatorRay

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!