목차
this 是啥" >this 是啥
웹 프론트엔드 JS 튜토리얼 JS 화살표 기능에 대한 자세한 설명

JS 화살표 기능에 대한 자세한 설명

Nov 26, 2019 pm 04:18 PM
js 화살표 기능

JS에서 화살표 함수는 일반 함수처럼 다양한 방식으로 사용될 수 있습니다. 그러나 일반적으로 콜백 함수와 같이 익명 함수 표현식이 필요할 때 사용됩니다.

JS 화살표 기능에 대한 자세한 설명

다음 예에서는 특히 map(), filter(), reduce()에 대한 콜백 함수인 화살표 함수의 예를 보여줍니다. > , sort() 및 기타 배열 메서드. map(), filter(), reduce(), sort()等数组方法。

const scores = [ 1, 28, 66, 666];
const maxScore = Math.max(...scores);

scores.map(score => +(score / maxScore).toFixed(2));
로그인 후 복사

乍一看,箭头函数似乎可以按常规函数来定义与使用,但事实并非如此。出于箭头函数的简洁性,它与常规函数有所不同,换一种看法,箭头函数也许可以把箭头函数看作是异常的 JS 函数。

【相关课程推荐:JavaScript视频教程

虽然箭头函数的语法非常简单,但这不是本文的重点。本文主要讲讲箭头函数与常规函数行为的差异,以及咱们如果利用这些差异来更好使用箭头函数。

 ● 无论在严格模式还是非严格模式下,箭头函数都不能具有重复的命名参数。

 ● 箭头函数没有arguments绑定。但是,它们可以访问最接近的非箭头父函数的arguments对象。

 ● 箭头函数永远不能用作构造函数,自然的不能使用new关键字调用它们,因此,对于箭头函数不存在prototype属性。

 ● 在函数的整个生命周期中,箭头函数内部的值保持不变,并且总是与接近的非箭头父函数中的值绑定。

命名函数参数

JS中的函数通常用命名参数定义。命名参数用于根据位置将参数映射到函数作用域中的局部变量。

来看看下面的函数:

function logParams (first, second, third) {
  console.log(first, second, third);
}

// first => 'Hello'
// second => 'World'
// third => '!!!'
logParams('Hello', 'World', '!!!'); // "Hello"  "World"  "!!!"

// first => { o: 3 }
// second => [ 1, 2, 3 ]
// third => undefined
logParams({ o: 3 }, [ 1, 2, 3 ]); // {o: 3}  [1, 2, 3]
로그인 후 복사

logParams()函数由三个命名参数定义: firstsecondthird。如果命名参数多于传递给函数的参数,则其余参数undefined

对于命名参数,JS函数在非严格模式下表现出奇怪的行为。在非严格模式下,JS函数允许有重复命名参数,来看看示例:

function logParams (first, second, first) {
  console.log(first, second);
}

// first => 'Hello'
// second => 'World'
// first => '!!!'
logParams('Hello', 'World', '!!!'); // "!!!"  "World"

// first => { o: 3 }
// second => [ 1, 2, 3 ]
// first => undefined
logParams({ o: 3 }, [ 1, 2, 3 ]); // undefined  [1, 2, 3]
로그인 후 복사

咱们可以看到,first参数重复了,因此,它被映射到传递给函数调用的第三个参数的值,覆盖了第一个参数,这不是一个让人喜欢的行为。

// 由于参数重复,严格模式会报错
function logParams (first, second, first) {
  "use strict";
  console.log(first, second);
}
로그인 후 복사

箭头函数如何处理重复的参数

关于箭头函数:

与常规函数不同,无论在严格模式还是非严格模式下,箭头函数都不允许重复参数,重复的参数将引发语法错误。

// 只要你敢写成重复的参数,我就敢死给你看
const logParams = (first, second, first) => {
  console.log(first, second);
}
로그인 후 복사

函数重载

函数重载是定义函数的能力,这样就可以根据不同的参数数量来调用对应的函数, JS 中可以利用绑定方式来实现这一功能。

来看个简单的重载函数,计算传入参数的平均值:

function average() {
  const length = arguments.length;

  if (length == 0) return 0;

  // 将参数转换为数组
  const numbers = Array.prototype.slice.call(arguments);

  const sumReduceFn = function (a, b) { return a + Number(b) };
  // 返回数组元素的总和除以数组的长度
  return numbers.reduce(sumReduceFn, 0) / length;
}
로그인 후 복사

这样函数可以用任意数量的参数调用,从0到函数可以接受的最大参数数量应该是255

average(); // 0
average('3o', 4, 5); // NaN
average('1', 2, '3', 4, '5', 6, 7, 8, 9, 10); // 5.5
average(1.75, 2.25, 3.5, 4.125, 5.875); // 3.5
로그인 후 복사

现在尝试使用剪头函数语法复制average()函数,一般咱们会觉得,这没啥难的,无法就这样:

const average = () => {
  const length = arguments.length;

  if (length == 0) return 0;

  const numbers = Array.prototype.slice.call(arguments);
  const sumReduceFn = function (a, b) { return a + Number(b) };

  return numbers.reduce(sumReduceFn, 0) / length;
}
로그인 후 복사

现在测试这个函数时,咱们会发现它会抛出一个引用错误,arguments 未定义。

咱们做错了啥

对于箭头函数:

与常规函数不同,arguments不存在于箭头函数中。但是,可以访问非箭头父函数的arguments对象。

基于这种理解,可以将average()函数修改为一个常规函数,该函数将返回立即调用的嵌套箭头函数执行的结果,该嵌套箭头函数就能够访问父函数的arguments

function average() {
  return (() => {
    const length = arguments.length;

    if (length == 0) return 0;

    const numbers = Array.prototype.slice.call(arguments);
    const sumReduceFn = function (a, b) { return a + Number(b) };

    return numbers.reduce(sumReduceFn, 0) / length;
  })();
}
로그인 후 복사

这样就可以解决了arguments对象没有定义的问题,但这种狗屎做法显然很多余了。

做点不一样的

对于上面问题是否存在替代方法呢,可以使用 es6 的 rest 参数。

使用ES6 rest 参数,咱们可以得到一个数组,该数组保存了传递给该函数的所有的参数。rest语法适用于所有类型的函数,无论是常规函数还是箭头函数。

const average = (...args) => {
  if (args.length == 0) return 0;
  const sumReduceFn = function (a, b) { return a + Number(b) };

  return args.reduce(sumReduceFn, 0) / args.length;
}
로그인 후 복사

对于使用rest参数需要注意一些事项:

 ● rest参数与函数内部的arguments对象不同。rest参数是一个实际的函数参数,而arguments

function baseConvert (num, fromRadix = 10, toRadix = 10) {
  if (arguments.length < 3) {
    // swap variables using array destructuring
    [toRadix, fromRadix] = [fromRadix, toRadix];
  }
  return parseInt(num, fromRadix).toString(toRadix);
}
로그인 후 복사
로그인 후 복사

얼핏 보면 화살표 함수를 일반 함수처럼 정의해서 사용할 수 있을 것 같지만 그렇지 않습니다. 화살표 함수는 단순성 때문에 일반 함수와는 다릅니다. 다른 관점에서 보면 화살표 함수는 비정상적인 JS 함수로 간주될 수도 있습니다. 🎜🎜【관련 강좌 추천: JavaScript 동영상 튜토리얼]🎜🎜화살표 기능이 있지만 구문은 매우 간단하지만 이것이 이 기사의 초점은 아닙니다. 이 기사에서는 주로 화살표 함수와 일반 함수의 동작 차이점과 이러한 차이점을 사용하여 화살표 함수를 더 잘 사용할 수 있는 방법에 대해 설명합니다. 🎜🎜● 엄격 모드이든 비엄격 모드이든 화살표 함수는 중복된 명명된 매개 변수를 가질 수 없습니다. 🎜🎜● 화살표 함수에는 인수 바인딩이 없습니다. 그러나 화살표가 아닌 가장 가까운 상위 함수의 arguments 객체에 액세스할 수 있습니다. 🎜🎜● 화살표 함수는 생성자로 사용할 수 없으며 당연히 new 키워드를 사용하여 호출할 수 없습니다. 따라서 화살표 함수에는 prototype 속성이 없습니다. 🎜🎜● 화살표 함수 내부의 값은 함수 수명 내내 변경되지 않고 항상 가장 가까운 비화살표 상위 함수의 값에 바인딩됩니다. 🎜🎜🎜이름이 지정된 함수 매개변수🎜🎜🎜JS의 함수는 일반적으로 이름이 지정된 매개변수로 정의됩니다. 명명된 매개변수는 매개변수를 함수 범위의 지역 변수에 위치적으로 매핑하는 데 사용됩니다. 🎜🎜다음 함수를 살펴보겠습니다. 🎜
// num => 123, fromRadix => 10, toRadix => 10
console.log(baseConvert(123)); // "123"

// num => 255, fromRadix => 10, toRadix => 2
console.log(baseConvert(255, 2)); // "11111111"

// num => 'ff', fromRadix => 16, toRadix => 8
console.log(baseConvert('ff', 16, 8)); // "377"
로그인 후 복사
로그인 후 복사
🎜 logParams() 함수는 세 개의 명명된 매개변수인 first, second로 정의됩니다. 그리고 세 번째. 함수에 전달된 것보다 더 많은 명명된 인수가 있는 경우 나머지 인수는 정의되지 않음입니다. 🎜🎜JS 함수는 명명된 매개변수를 사용하는 비엄격 모드에서 이상한 동작을 나타냅니다. 비엄격 모드에서 JS 함수는 이름이 지정된 매개변수의 반복을 허용합니다. 예를 살펴보겠습니다. 🎜
const baseConvert = (num, ...args) => {
  // 解构`args`数组和
  // 设置`fromRadix`和`toRadix`局部变量
  let [fromRadix = 10, toRadix = 10] = args;

  if (args.length < 2) {
    // 使用数组解构交换变量
    [toRadix, fromRadix] = [fromRadix, toRadix];
  }

  return parseInt(num, fromRadix).toString(toRadix);
}
로그인 후 복사
로그인 후 복사
🎜 첫 번째 매개변수가 반복되어 전달된 매개변수에 매핑되는 것을 볼 수 있습니다. 세 번째 매개변수의 값은 첫 번째 매개변수를 덮어쓰는데 이는 바람직한 동작이 아닙니다. 🎜
function Square (length = 10) {
  this.length = parseInt(length) || 10;

  this.getArea = function() {
    return Math.pow(this.length, 2);
  }

  this.getPerimeter = function() {
    return 4 * this.length;
  }
}

const square = new Square();

console.log(square.length); // 10
console.log(square.getArea()); // 100
console.log(square.getPerimeter()); // 40

console.log(typeof square); // "object"
console.log(square instanceof Square); // true
로그인 후 복사
로그인 후 복사
🎜🎜화살표 함수가 반복 인수를 처리하는 방법🎜🎜🎜🎜화살표 함수 정보: 🎜🎜🎜은 엄격 모드 여부에 관계없이 일반 함수와 다릅니다. 엄격 모드에서 화살표 함수는 반복되는 매개변수를 허용하지 않습니다. 반복되는 매개변수는 구문 오류를 발생시킵니다. 🎜
function Square (length = 10) {
  this.length = parseInt(length) || 10;
}

Square.prototype.getArea = function() {
  return Math.pow(this.length, 2);
}

Square.prototype.getPerimeter = function() {
  return 4 * this.length;
}

const square = new Square();

console.log(square.length); // 10
console.log(square.getArea()); // 100
console.log(square.getPerimeter()); // 40

console.log(typeof square); // "object"
console.log(square instanceof Square); // true
로그인 후 복사
로그인 후 복사
🎜🎜함수 오버로딩🎜🎜🎜함수 오버로딩은 함수를 정의하여 매개변수 수에 따라 해당 함수를 호출할 수 있도록 하는 기능입니다. 이 기능을 달성하기 위해 JS에서 바인딩을 사용할 수 있습니다. 🎜🎜전달된 매개변수의 평균을 계산하는 간단한 오버로드된 함수를 살펴보겠습니다. 🎜
const Square = (length = 10) => {
  this.length = parseInt(length) || 10;
}

// throws an error
const square = new Square(5);

// throws an error
Square.prototype.getArea = function() {
  return Math.pow(this.length, 2);
}

console.log(Square.prototype); // undefined
로그인 후 복사
로그인 후 복사
🎜이렇게 하면 0부터 함수가 허용할 수 있는 최대 매개변수 수까지 원하는 수의 매개변수를 사용하여 함수를 호출할 수 있습니다. 255 code>여야 합니다. 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">function processFormData (evt) {   evt.preventDefault();   const form = this.closest('form');   const data = new FormData(form);   const { action: url, method } = form; } button.addEventListener('click', processFormData, false);</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div>🎜이제 head-cut 함수 구문을 사용하여 <code>average() 함수를 복사해 보세요. 일반적으로 우리는 이것이 어렵지 않다고 생각하고 이것만 할 수는 없습니다. 🎜
this.closest('form');
로그인 후 복사
로그인 후 복사
🎜이제 이 함수를 테스트하면 참조 오류가 발생하고 인수가 정의되지 않음을 알 수 있습니다. 🎜🎜🎜우리가 무엇을 잘못했나요🎜🎜🎜화살표 함수의 경우: 🎜🎜일반 함수와 달리 인수가 존재하지 않습니다. 화살표 기능에서. 그러나 화살표가 아닌 상위 함수의 인수 객체에 액세스하는 것은 가능합니다. 🎜🎜이러한 이해를 바탕으로 average() 함수를 일반 함수로 수정하면 즉시 호출된 중첩 화살표 함수의 결과를 반환하고 중첩 화살표 함수에서 액세스할 수 있게 됩니다. 부모 함수의 인수입니다. 🎜
const processFormData = (evt) => {
  evt.preventDefault();

  const form = this.closest('form');
  const data = new FormData(form);
  const { action: url, method } = form;
}

button.addEventListener('click', processFormData, false);
로그인 후 복사
로그인 후 복사
🎜이렇게 하면 arguments 개체가 정의되지 않은 문제를 해결할 수 있지만, 이 헛소리 접근 방식은 분명히 중복됩니다. 🎜🎜🎜뭔가 다르게 해보세요🎜🎜🎜위 문제에 대한 대안이 있나요? es6의 rest 매개변수를 사용할 수 있나요? . 🎜🎜ES6 rest 매개변수를 사용하면 함수에 전달된 모든 매개변수를 저장하는 배열을 얻을 수 있습니다. rest 구문은 일반 함수든 화살표 함수든 모든 유형의 함수에 작동합니다. 🎜
button.addEventListener('click', processFormData.bind(button), false);
로그인 후 복사
로그인 후 복사
🎜rest 매개변수를 사용할 때 주의해야 할 사항이 있습니다: 🎜🎜● rest 매개변수는 인수와 다릅니다. > 함수 내부의 객체. rest 매개변수는 실제 함수 매개변수인 반면, arguments 개체는 함수 범위에 바인딩된 내부 개체입니다. 🎜

 ● 一个函数只能有一个rest参数,而且它必须位于最后一个参数。这意味着函数可以包含命名参数和rest参数的组合。

 ● rest 参数与命名参数一起使用时,它不包含所有传入的参数。但是,当它是惟一的函数参数时,表示函数参数。另一方面,函数的arguments对象总是捕获所有函数的参数。

 ● rest参数指向包含所有捕获函数参数的数组对象,而arguments对象指向包含所有函数参数的类数组对象。

接着考虑另一个简单的重载函数,该函数将数字根据传入的进制转换为另一个类的进制数。 可以使用一到三个参数调用该函数。 但是,当使用两个或更少的参数调用它时,它会交换第二个和第三个函数参数。如下所示:

function baseConvert (num, fromRadix = 10, toRadix = 10) {
  if (arguments.length < 3) {
    // swap variables using array destructuring
    [toRadix, fromRadix] = [fromRadix, toRadix];
  }
  return parseInt(num, fromRadix).toString(toRadix);
}
로그인 후 복사
로그인 후 복사

调用 baseConvert 方法:

// num => 123, fromRadix => 10, toRadix => 10
console.log(baseConvert(123)); // "123"

// num => 255, fromRadix => 10, toRadix => 2
console.log(baseConvert(255, 2)); // "11111111"

// num => 'ff', fromRadix => 16, toRadix => 8
console.log(baseConvert('ff', 16, 8)); // "377"
로그인 후 복사
로그인 후 복사

使用箭头函数来重写上面的方法:

const baseConvert = (num, ...args) => {
  // 解构`args`数组和
  // 设置`fromRadix`和`toRadix`局部变量
  let [fromRadix = 10, toRadix = 10] = args;

  if (args.length < 2) {
    // 使用数组解构交换变量
    [toRadix, fromRadix] = [fromRadix, toRadix];
  }

  return parseInt(num, fromRadix).toString(toRadix);
}
로그인 후 복사
로그인 후 복사

构造函数

可以使用new关键字调用常规JS函数,该函数作为类构造函数用于创建新的实例对象。

function Square (length = 10) {
  this.length = parseInt(length) || 10;

  this.getArea = function() {
    return Math.pow(this.length, 2);
  }

  this.getPerimeter = function() {
    return 4 * this.length;
  }
}

const square = new Square();

console.log(square.length); // 10
console.log(square.getArea()); // 100
console.log(square.getPerimeter()); // 40

console.log(typeof square); // "object"
console.log(square instanceof Square); // true
로그인 후 복사
로그인 후 복사

当使用new关键字调用常规JS函数时,将调用函数内部[[Construct]]方法来创建一个新的实例对象并分配内存。之后,函数体将正常执行,并将this映射到新创建的实例对象。最后,函数隐式地返回 this(新创建的实例对象),只是在函数定义中指定了一个不同的返回值。

此外,所有常规JS函数都有一个prototype属性。函数的prototype属性是一个对象,它包含函数创建的所有实例对象在用作构造函数时共享的属性和方法。

以下是对前面的Square函数的一个小修改,这次它从函数的原型上的方法,而不是构造函数本身。

function Square (length = 10) {
  this.length = parseInt(length) || 10;
}

Square.prototype.getArea = function() {
  return Math.pow(this.length, 2);
}

Square.prototype.getPerimeter = function() {
  return 4 * this.length;
}

const square = new Square();

console.log(square.length); // 10
console.log(square.getArea()); // 100
console.log(square.getPerimeter()); // 40

console.log(typeof square); // "object"
console.log(square instanceof Square); // true
로그인 후 복사
로그인 후 복사

如下所知,一切仍然按预期工作。 事实上,这里有一个小秘密:ES6 类在后台执行类似于上面代码片段的操作 - 类(class)只是个语法糖。

那么箭头函数呢

它们是否也与常规JS函数共享此行为?答案是否定的。关于箭头函数:

与常规函数不同,箭头函数永远不能使用new关键字调用,因为它们没有[[Construct]]方法。 因此,箭头函数也不存在prototype属性。

箭头函数不能用作构造函数,无法使用new关键字调用它们,如果这样做了会抛出一个错误,表明该函数不是构造函数。

因此,对于箭头函数,不存在可以作为构造函数调用的函数内部的new.target等绑定,相反,它们使用最接近的非箭头父函数的new.target值。

此外,由于无法使用new关键字调用箭头函数,因此实际上不需要它们具有原型。 因此,箭头函数不存在prototype属性。

由于箭头函数的prototypeundefined,尝试使用属性和方法来扩充它,或者访问它上面的属性,都会引发错误。

const Square = (length = 10) => {
  this.length = parseInt(length) || 10;
}

// throws an error
const square = new Square(5);

// throws an error
Square.prototype.getArea = function() {
  return Math.pow(this.length, 2);
}

console.log(Square.prototype); // undefined
로그인 후 복사
로그인 후 복사

this 是啥

JS函数的每次调用都与调用上下文相关联,这取决于函数是如何调用的,或者在哪里调用的。

函数内部this值依赖于函数在调用时的调用上下文,这通常会让开发人员不得不问自己一个问题:this值是啥。

下面是对不同类型的函数调用this指向一些总结:

 ● 使用new关键字调用:this指向由函数的内部[[Construct]]方法创建的新实例对象。this(新创建的实例对象)通常在默认情况下返回,除了在函数定义中显式指定了不同的返回值。

 ● 不使用new关键字直接调用:在非严格模式下,this指向window对象(浏览器中)。然而,在严格模式下,this值为undefined;因此,试图访问或设置此属性将引发错误。

 ● 间接使用绑定对象调用Function.prototype对象提供了三种方法,可以在调用函数时将函数绑定到任意对象,即:call()apply()bind()。 使用这些方法调用函数时,this指向指定的绑定对象。

 ● 作为对象方法调用this指向调用函数(方法)的对象,无论该方法是被定义为对象的自己的属性还是从对象的原型链中解析。

 ● 作为事件处理程序调用:对于用作DOM事件侦听器的常规函数,this指向触发事件的目标对象、DOM元素、documentwindow

再来看个函数,该函数将用作单击事件侦听器,例如,表单提交按钮:

function processFormData (evt) {
  evt.preventDefault();

  const form = this.closest('form');

  const data = new FormData(form);
  const { action: url, method } = form;
}

button.addEventListener('click', processFormData, false);
로그인 후 복사
로그인 후 복사

与前面看到的一样,事件侦听器函数中的 this值是触发单击事件的DOM元素,在本例中是button

因此,可以使用以下命令指向submit按钮的父表单

this.closest('form');
로그인 후 복사
로그인 후 복사

如果将函数更改为箭头函数语法,会发生什么?

const processFormData = (evt) => {
  evt.preventDefault();

  const form = this.closest('form');
  const data = new FormData(form);
  const { action: url, method } = form;
}

button.addEventListener('click', processFormData, false);
로그인 후 복사
로그인 후 복사

如果现在尝试此操作,咱们就得到一个错误。从表面上看,this 的值并不是各位想要的。由于某种原因,它不再指向button元素,而是指向window对象。

如何修复this指向

利用上面提到的 Function.prototype.bind() 强制将this值绑定到button元素:

button.addEventListener('click', processFormData.bind(button), false);
로그인 후 복사
로그인 후 복사

但这似乎不是各位想要的解决办法。this仍然指向window对象。这是箭头函数特有的问题吗?这是否意味着箭头函数不能用于依赖于this的事件处理?

为什么会搞错

关于箭头函数的最后一件事:

与常规函数不同,箭头函数没有this的绑定。 this的值将解析为最接近的非箭头父函数或全局对象的值。

这解释了为什么事件侦听器箭头函数中的this值指向window 对象(全局对象)。 由于它没有嵌套在父函数中,因此它使用来自最近的父作用域的this值,该作用域是全局作用域。

但是,这并不能解释为什么不能使用bind()将事件侦听器箭头函数绑定到button元素。对此有一个解释:

与常规函数不同,内部箭头函数的this值保持不变,并且无论调用上下文如何,都不能在其整个生命周期中更改。

箭头函数的这种行为使得JS引擎可以优化它们,因为可以事先确定函数绑定。

考虑一个稍微不同的场景,其中事件处理程序是使用对象方法中的常规函数定义的,并且还取决于同一对象的另一个方法:

({
  _sortByFileSize: function (filelist) {
    const files = Array.from(filelist).sort(function (a, b) {
      return a.size - b.size;
    });

    return files.map(function (file) {
      return file.name;
    });
  },

  init: function (input) {
    input.addEventListener('change', function (evt) {
      const files = evt.target.files;
      console.log(this._sortByFileSize(files));
    }, false);
  }

}).init(document.getElementById('file-input'));
로그인 후 복사

上面是一个一次性的对象,该对象带有_sortByFileSize()方法和init()方法,并立即调init方法。init()方法接受一个input元素,并为input元素设置一个更改事件处理程序,该事件处理程序按文件大小对上传的文件进行排序,并打印在浏览器的控制台。

如果测试这段代码,会发现,当选择要上载的文件时,文件列表不会被排序并打印到控制台;相反,会控制台上抛出一个错误,问题就出在这一行:

console.log(this._sortByFileSize(files));
로그인 후 복사

在事件监听器函数内部,this 指向 input 元素 因此this._sortByFileSizeundefined

要解决此问题,需要将事件侦听器中的this绑定到包含方法的外部对象,以便可以调用this._sortByFileSize()。 在这里,可以使用bind(),如下所示:

init: function (input) {
  input.addEventListener('change', (function (evt) {
    const files = evt.target.files;
    console.log(this._sortByFileSize(files));
  }).bind(this), false);
}
로그인 후 복사
로그인 후 복사

现在一切正常。这里不使用bind(),可以简单地用一个箭头函数替换事件侦听器函数。箭头函数将使用父init()方法中的this的值:

init: function (input) {
  input.addEventListener('change', (function (evt) {
    const files = evt.target.files;
    console.log(this._sortByFileSize(files));
  }).bind(this), false);
}
로그인 후 복사
로그인 후 복사

再考虑一个场景,假设有一个简单的计时器函数,可以将其作为构造函数调用来创建以秒为单位的倒计时计时器。使用setInterval()进行倒计时,直到持续时间过期或间隔被清除为止,如下所示:

function Timer (seconds = 60) {
  this.seconds = parseInt(seconds) || 60;
  console.log(this.seconds);

  this.interval = setInterval(function () {
    console.log(--this.seconds);

    if (this.seconds == 0) {
      this.interval && clearInterval(this.interval);
    }
  }, 1000);
}

const timer = new Timer(30);
로그인 후 복사

如果运行这段代码,会看到倒计时计时器似乎被打破了,在控制台上一直打印 NaN

这里的问题是,在传递给setInterval()的回调函数中,this指向全局window对象,而不是Timer()函数作用域内新创建的实例对象。因此,this.secondsthis.interval  都是undefined的。

与之前一样,要修复这个问题,可以使用bind()setInterval()回调函数中的this值绑定到新创建的实例对象,如下所示

function Timer (seconds = 60) {
  this.seconds = parseInt(seconds) || 60;
  console.log(this.seconds);

  this.interval = setInterval((function () {
    console.log(--this.seconds);

    if (this.seconds == 0) {
      this.interval && clearInterval(this.interval);
    }
  }).bind(this), 1000);
}
로그인 후 복사

或者,更好的方法是,可以用一个箭头函数替换setInterval()回调函数,这样它就可以使用最近的非箭头父函数的this值:

function Timer (seconds = 60) {
  this.seconds = parseInt(seconds) || 60;
  console.log(this.seconds);

  this.interval = setInterval(() => {
    console.log(--this.seconds);

    if (this.seconds == 0) {
      this.interval && clearInterval(this.interval);
    }
  }, 1000);
}
로그인 후 복사

现在理解了箭头函数如何处理this关键字,还需要注意箭头函数对于需要保留this值的情况并不理想 - 例如,在定义需要引用的对象方法时 使用需要引用目标对象的方法来扩展对象或扩充函数的原型。

不存在的绑定

在本文中,已经看到了一些绑定,这些绑定可以在常规JS函数中使用,但是不存在用于箭头函数的绑定。相反,箭头函数从最近的非箭头父函数派生此类绑定的值。

总之,下面是箭头函数中不存在绑定的列表:

 ● arguments:调用时传递给函数的参数列表

 ● new.target:使用new关键字作为构造函数调用的函数的引用

 ● super:对函数所属对象原型的引用,前提是该对象被定义为一个简洁的对象方法

 ● this:对函数的调用上下文对象的引用

原文:https://s0dev0to.icopy.site/bnevilleoneill/anomalies-in-javascript-arrow-functions-2afh

为了保证的可读性,本文采用意译而非直译。

本文来自 js教程 栏目,欢迎学习!

위 내용은 JS 화살표 기능에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌
Will R.E.P.O. 크로스 플레이가 있습니까?
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

JS 및 Baidu Maps를 사용하여 지도 이동 기능을 구현하는 방법 JS 및 Baidu Maps를 사용하여 지도 이동 기능을 구현하는 방법 Nov 21, 2023 am 10:00 AM

JS 및 Baidu Map을 사용하여 지도 팬 기능을 구현하는 방법 Baidu Map은 지리 정보, 위치 지정 및 기타 기능을 표시하기 위해 웹 개발에 자주 사용되는 널리 사용되는 지도 서비스 플랫폼입니다. 이 글에서는 JS와 Baidu Map API를 사용하여 지도 이동 기능을 구현하는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 1. 준비 바이두 맵 API를 사용하기 전에 먼저 바이두 맵 오픈 플랫폼(http://lbsyun.baidu.com/)에서 개발자 계정을 신청하고 애플리케이션을 만들어야 합니다. 생성 완료

권장 사항: 우수한 JS 오픈 소스 얼굴 감지 및 인식 프로젝트 권장 사항: 우수한 JS 오픈 소스 얼굴 감지 및 인식 프로젝트 Apr 03, 2024 am 11:55 AM

얼굴 검출 및 인식 기술은 이미 상대적으로 성숙하고 널리 사용되는 기술입니다. 현재 가장 널리 사용되는 인터넷 응용 언어는 JS입니다. 웹 프런트엔드에서 얼굴 감지 및 인식을 구현하는 것은 백엔드 얼굴 인식에 비해 장점과 단점이 있습니다. 장점에는 네트워크 상호 작용 및 실시간 인식이 줄어 사용자 대기 시간이 크게 단축되고 사용자 경험이 향상된다는 단점이 있습니다. 모델 크기에 따라 제한되고 정확도도 제한됩니다. js를 사용하여 웹에서 얼굴 인식을 구현하는 방법은 무엇입니까? 웹에서 얼굴 인식을 구현하려면 JavaScript, HTML, CSS, WebRTC 등 관련 프로그래밍 언어 및 기술에 익숙해야 합니다. 동시에 관련 컴퓨터 비전 및 인공지능 기술도 마스터해야 합니다. 웹 측면의 디자인으로 인해 주목할 가치가 있습니다.

주식 분석을 위한 필수 도구: PHP 및 JS를 사용하여 캔들 차트를 그리는 단계를 알아보세요. 주식 분석을 위한 필수 도구: PHP 및 JS를 사용하여 캔들 차트를 그리는 단계를 알아보세요. Dec 17, 2023 pm 06:55 PM

주식 분석을 위한 필수 도구: PHP 및 JS에서 캔들 차트를 그리는 단계를 배우십시오. 인터넷과 기술의 급속한 발전으로 주식 거래는 많은 투자자에게 중요한 방법 중 하나가 되었습니다. 주식분석은 투자자의 의사결정에 있어 중요한 부분이며 캔들차트는 기술적 분석에 널리 사용됩니다. PHP와 JS를 사용하여 캔들 차트를 그리는 방법을 배우면 투자자가 더 나은 결정을 내리는 데 도움이 되는 보다 직관적인 정보를 얻을 수 있습니다. 캔들스틱 차트는 주가를 캔들스틱 형태로 표시하는 기술 차트입니다. 주가를 보여주네요

PHP와 JS를 사용하여 주식 촛대 차트를 만드는 방법 PHP와 JS를 사용하여 주식 촛대 차트를 만드는 방법 Dec 17, 2023 am 08:08 AM

PHP와 JS를 사용하여 주식 캔들 차트를 만드는 방법 주식 캔들 차트는 주식 시장에서 흔히 사용되는 기술 분석 그래픽으로 시가, 종가, 최고가 등의 데이터를 그려서 투자자가 주식을 보다 직관적으로 이해할 수 있도록 도와줍니다. 주식의 최저 가격. 이 기사에서는 특정 코드 예제와 함께 PHP 및 JS를 사용하여 주식 캔들 차트를 만드는 방법을 설명합니다. 1. 준비 시작하기 전에 다음 환경을 준비해야 합니다. 1. PHP를 실행하는 서버 2. HTML5 및 Canvas를 지원하는 브라우저 3

JS 및 Baidu Maps를 사용하여 지도 히트맵 기능을 구현하는 방법 JS 및 Baidu Maps를 사용하여 지도 히트맵 기능을 구현하는 방법 Nov 21, 2023 am 09:33 AM

JS 및 Baidu Maps를 사용하여 지도 열 지도 기능을 구현하는 방법 소개: 인터넷과 모바일 장치의 급속한 발전으로 지도는 일반적인 응용 시나리오가 되었습니다. 시각적 표시 방법인 히트맵은 데이터 분포를 보다 직관적으로 이해하는 데 도움이 될 수 있습니다. 이 기사에서는 JS 및 Baidu Map API를 사용하여 지도 히트맵 기능을 구현하는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 준비 작업: 시작하기 전에 Baidu 개발자 계정, 애플리케이션 생성, 해당 AP 획득 등의 항목을 준비해야 합니다.

JS와 Baidu Map을 활용하여 지도 클릭 이벤트 처리 기능을 구현하는 방법 JS와 Baidu Map을 활용하여 지도 클릭 이벤트 처리 기능을 구현하는 방법 Nov 21, 2023 am 11:11 AM

JS 및 Baidu Maps를 사용하여 지도 클릭 이벤트 처리 기능을 구현하는 방법 개요: 웹 개발에서는 지리적 위치 및 지리적 정보를 표시하기 위해 지도 기능을 사용해야 하는 경우가 많습니다. 지도에서의 클릭 이벤트 처리는 지도 기능에서 일반적으로 사용되는 중요한 부분입니다. 이 글에서는 JS와 Baidu Map API를 사용하여 지도의 클릭 이벤트 처리 기능을 구현하는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 단계: Baidu Map API 파일 가져오기 먼저 다음 코드를 통해 Baidu Map API 파일을 가져올 수 있습니다.

PHP 및 JS 개발 팁: 주식 캔들 차트 그리기 방법 익히기 PHP 및 JS 개발 팁: 주식 캔들 차트 그리기 방법 익히기 Dec 18, 2023 pm 03:39 PM

인터넷 금융의 급속한 발전으로 인해 주식 투자는 점점 더 많은 사람들의 선택이 되었습니다. 주식 거래에서 캔들 차트는 주가의 변화 추세를 보여주고 투자자가 보다 정확한 결정을 내리는 데 도움이 되는 일반적으로 사용되는 기술적 분석 방법입니다. 이 기사에서는 PHP와 JS의 개발 기술을 소개하고 독자가 주식 캔들 차트를 그리는 방법을 이해하도록 유도하며 구체적인 코드 예제를 제공합니다. 1. 주식 캔들 차트의 이해 주식 캔들 차트를 그리는 방법을 소개하기 전에 먼저 캔들 차트가 무엇인지부터 이해해야 합니다. 캔들스틱 차트는 일본인이 개발했습니다.

JS 및 Baidu Maps를 사용하여 지도 다각형 그리기 기능을 구현하는 방법 JS 및 Baidu Maps를 사용하여 지도 다각형 그리기 기능을 구현하는 방법 Nov 21, 2023 am 10:53 AM

JS 및 Baidu Maps를 사용하여 지도 다각형 그리기 기능을 구현하는 방법 현대 웹 개발에서 지도 애플리케이션은 일반적인 기능 중 하나가 되었습니다. 지도에 다각형을 그리면 사용자가 보고 분석할 특정 영역을 표시하는 데 도움이 될 수 있습니다. 이 기사에서는 JS 및 Baidu Map API를 사용하여 지도 다각형 그리기 기능을 구현하는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 먼저 Baidu Map API를 도입해야 합니다. 다음 코드를 사용하여 Baidu Map API의 JavaScript를 HTML 파일로 가져올 수 있습니다.

See all articles