# Function and Arrow Function Scope in JavaScript: 4 Critical Differences Explained

> Master JavaScript function and arrow function scope differences. Understand how `this` behaves in each to avoid common bugs and write cleaner code.

- Repository: [Lydia Hallie/javascript-questions](https://github.com/lydiahallie/javascript-questions)
- Tags: deep-dive
- Published: 2026-03-04

---

**Regular functions create their own dynamic `this` context at invocation time, while arrow functions inherit `this` lexically from their parent scope and cannot be rebound.**

Understanding the distinction between function and arrow function scope is essential for avoiding common JavaScript pitfalls. According to the `lydiahallie/javascript-questions` repository—a widely-used resource for JavaScript interview preparation—these scope differences primarily manifest in how `this` binding, the `arguments` object, and constructor behavior are handled.

## How Function and Arrow Function Scope Differ

### Lexical vs. Dynamic `this` Binding

The most significant difference lies in `this` resolution. Regular functions establish `this` based on the invocation context—whether called as a method, constructor, or with `call`/`apply`/`bind`. Arrow functions capture `this` from their enclosing lexical environment at definition time.

As documented in [`README.md`](https://github.com/lydiahallie/javascript-questions/blob/main/README.md) lines 141-145 of the repository: "With arrow functions, the `this` keyword refers to its current surrounding scope, unlike regular functions! This means that when we call `perimeter`, it doesn't refer to the shape object, but to its surrounding scope."

### The `arguments` Object Availability

Regular functions possess their own `arguments` object containing passed parameters. Arrow functions lack this object entirely, inheriting `arguments` from the outer scope if it exists, or throwing a `ReferenceError` if accessed directly.

### Constructor and Prototype Limitations

Regular functions can serve as constructors when invoked with `new`, possessing an internal `[[Construct]]` method and a `prototype` property. Arrow functions cannot be used as constructors—attempting to call them with `new` throws a `TypeError`—and they do not have a `prototype` property.

## Practical Code Examples

### Object Method Context from README.md

The repository provides a concrete demonstration of scope differences in object methods:

```javascript
const shape = {
  radius: 10,
  // Regular function: `this` refers to `shape` when called as `shape.diameter()`
  diameter() {
    return this.radius * 2;          // → 20
  },
  // Arrow function: `this` is taken from the surrounding (global) scope
  perimeter: () => 2 * Math.PI * this.radius,
};

console.log(shape.diameter());  // 20
console.log(shape.perimeter()); // NaN (because `this.radius` is undefined)

```

### Attempting to Rebind `this`

Arrow functions ignore `bind`, `call`, and `apply` attempts:

```javascript
function Person(name) {
  this.name = name;
}

// Regular function can be rebound
const greet = function () {
  return `Hi, I'm ${this.name}`;
};
const boundGreet = greet.bind({ name: 'Alice' });
console.log(boundGreet()); // Hi, I'm Alice

// Arrow function ignores bind()
const arrowGreet = () => `Hi, I'm ${this.name}`;
const boundArrow = arrowGreet.bind({ name: 'Bob' });
console.log(boundArrow()); // Hi, I'm undefined (uses global `this`)

```

### Constructor Usage

Demonstrating the instantiation limitation:

```javascript
function Car() { 
  this.wheels = 4; 
}
const myCar = new Car(); // Works fine

const ArrowCar = () => { 
  this.wheels = 4; 
};
// const myArrowCar = new ArrowCar(); 
// TypeError: ArrowCar is not a constructor

```

## Summary

- **Regular functions** create their own `this` context determined at invocation time, support the `arguments` object, and can serve as constructors with `new`.
- **Arrow functions** inherit `this` lexically from their parent scope, lack their own `arguments` object, and cannot be used as constructors or rebound with `call`/`apply`/`bind`.
- The `lydiahallie/javascript-questions` repository highlights these differences in [`README.md`](https://github.com/lydiahallie/javascript-questions/blob/main/README.md) lines 141-145, demonstrating how arrow functions in object literals capture the global scope instead of the object context.

## Frequently Asked Questions

### Can you change the `this` value of an arrow function using `bind`, `call`, or `apply`?

No. Arrow functions capture `this` lexically from their surrounding scope at the time they are defined. Even if you attempt to use `Function.prototype.bind()`, `call()`, or `apply()`, the arrow function will continue to reference its original lexical `this` value.

### Why does an arrow function method return `NaN` or `undefined` when accessing object properties?

When an arrow function is defined as a method inside an object literal, it does not receive its own `this` binding. Instead, it inherits `this` from the enclosing scope—typically the global object (`window` in browsers) or `undefined` in strict mode. Since `this.radius` refers to the global scope rather than the object, the property returns `undefined`, causing mathematical operations to return `NaN`.

### Do arrow functions have an `arguments` object like regular functions?

No, arrow functions do not have their own `arguments` object. If you reference `arguments` inside an arrow function, it will look up the scope chain to find an `arguments` binding in an enclosing regular function, or throw a `ReferenceError` if none exists. To access function parameters in an arrow function, use rest parameters (`...args`) instead.

### Can arrow functions be used as constructors with the `new` keyword?

No, arrow functions cannot be used as constructors. They lack the internal `[[Construct]]` method required for constructor behavior, and they do not have a `prototype` property. Attempting to invoke an arrow function with `new` will throw a `TypeError` indicating that the function is not a constructor.