07.this指向~ES6初(118~126)

this

在JavaScript中,关键字this指向当前执行上下文的对象。具体来说,this的指向取决于它是如何被调用的。以下是一些常见情况下this的指向:

  1. 在全局作用域中,this指向全局对象(在浏览器中通常是window对象)。
  2. 在函数中,this的值取决于函数是如何被调用的。如果函数作为对象的方法被调用,this指向调用该函数的对象。如果函数被独立调用,this通常指向全局对象(在严格模式下是undefined)。
  3. 在构造函数中,this指向将要创建的新实例。
  4. 在事件处理程序中,this通常指向触发事件的元素。

需要注意的是,箭头函数中的this与普通函数不同,它没有自己的this值,而是继承自外层作用域的this。因此,箭头函数中的this是在定义时确定的,而不是在调用时确定的。

this指向

windows.test全局

obj函数

事件绑定this


改变this指向

call apply bind

在JavaScript中,call、apply和bind是用于改变函数执行上下文(this指向)的方法。

1. call() 方法

call() 方法允许您调用一个具有给定this值和参数的函数。它接受一个this值和一个参数列表。当使用call()方法调用函数时,第一个参数将成为函数内部的this值,后续参数将被传递给函数作为参数。

例如:

javascript 复制代码
   function greet(name) {
       console.log(`Hello, ${name}! I am ${this.name}.`);
   }

   const person = { name: 'Alice' };
   greet.call(person, 'Bob');
   // 输出: Hello, Bob! I am Alice.

2. apply() 方法

apply() 方法与call()方法类似,它也允许您调用一个具有给定this值和参数的函数。不同之处在于,apply()方法接受一个this值和一个参数数组。

例如:

javascript 复制代码
    function greet(name) {
        console.log(`Hello, ${name}! I am ${this.name}.`);
    }

    const person = { name: 'Alice' };
    greet.apply(person, ['Bob']);
    // 输出: Hello, Bob! I am Alice.

3. bind() 方法

bind() 方法创建一个新的函数,该函数在调用时将指定的this值和参数传递给原始函数。与call()和apply()方法不同,bind()方法不会立即执行函数,而是返回一个新函数,该函数在调用时将具有指定的this值。

例如:

javascript 复制代码
   function greet(name) {
       console.log(`Hello, ${name}! I am ${this.name}.`);
   }

   const person = { name: 'Alice' };
   const greetPerson = greet.bind(person);
   greetPerson('Bob');
   // 输出: Hello, Bob! I am Alice.

总结:call()和apply()方法可以立即调用函数并改变函数的this值,而bind()方法则创建一个新的函数,该函数在调用时具有指定的this值。


ES6


let vs var

在JavaScript中,letvar都是用来声明变量的关键字,但它们之间有一些区别。

  1. 作用域:var声明的变量的作用域是整个函数,而let声明的变量的作用域是块级作用域,比如{}内部。
  2. 变量提升:使用var声明的变量存在变量提升,即在声明变量之前就可以访问该变量,而使用let声明的变量不存在变量提升,只有在声明之后才能访问该变量。
  3. 重复声明:使用var可以重复声明同一个变量,而使用let在同一个作用域内不能重复声明同一个变量。
  4. 全局对象属性:使用var声明的全局变量会成为全局对象的属性,而使用let声明的全局变量不会成为全局对象的属性。

let vs const

在JavaScript中,letconst都是用来声明变量的关键字,但它们之间有一些区别。

  1. 可变性:使用let声明的变量是可变的,即可以重新赋值。而使用const声明的变量是不可变的,即一旦赋值就不能再改变。

  2. 块级作用域:letconst都有块级作用域,即在{}内部声明的变量只在该块内有效。

  3. 变量提升:let声明的变量不存在变量提升,而const也不存在变量提升。

  4. 重复声明:在同一个作用域内,使用letconst都不能重复声明同一个变量。


案例-块级作用域

以下是一个简单的 JavaScript 示例,演示了块级作用域的概念:

javascript 复制代码
function blockScopeExample() {
  var x = 10;
  
  if (true) {
    var y = 20; // y在整个函数作用域内都是可见的
    let z = 30; // z只在if语句块内部可见
    console.log(x); // 10
    console.log(y); // 20
    console.log(z); // 30
  }
  
  console.log(x); // 10
  console.log(y); // 20
  console.log(z); // Uncaught ReferenceError: z is not defined
}

blockScopeExample();

在这个示例中,变量 x 在整个函数作用域内都是可见的,而变量 y 使用 var 声明也在整个函数作用域内可见,但变量 z 使用 let 声明只在 if 语句块内部可见。当我们尝试在 if 语句块外部访问变量 z 时,会收到一个 ReferenceError,因为 z 只在 if 语句块内部有效,这展示了块级作用域的概念。


箭头函数

ES6箭头函数是一种简洁的函数定义语法,它使用箭头符号(=>)来声明函数。箭头函数具有以下特点:

1. 只有一个形参时省略小括号

2. 只有只有一句代码,返回值时省略{}

3. map示例

4. 对象特殊情况

5. 没有arguments

在箭头函数中,没有自己的 arguments 对象。箭头函数的参数是固定的,它们不会像普通函数那样具有自己的 arguments 对象。如果需要访问参数,可以直接使用参数的名称来获取参数的值,而不是通过 arguments 对象。

例如:

ini 复制代码
const sum = (a, b) => {
  console.log(a + b);
};

sum(2, 3); // 输出 5

在上面的例子中,箭头函数直接使用参数 a 和 b 来获取传入的值,而不是使用 arguments 对象。

6. 箭头函数没有this

例如:

在下面的例子中,箭头函数内部的 this 指向的是定义该箭头函数时的上下文中的 this,而不是在调用时的上下文中的 this。

javascript 复制代码
function Person(name) 
{
  this.name = name;
  this.greet = function() 
  {
    setTimeout(() => 
    {
      console.log('Hello, my name is ' + this.name);
    }, 1000);
  };
}

const person1 = new Person('John');
person1.greet(); // 输出 "Hello, my name is John"(在1秒后)

在这个例子中,箭头函数内部的 this 指向的是 Person 函数内部的 this,而不是 setTimeout 函数的上下文中的 this。


ES6的解构赋值

ES6的解构赋值是一种方便的语法,用于从数组或对象中提取数据,并赋值给变量。它可以让我们更快速地获取和使用数组或对象中的数据。

1. 数组解构赋值:

ini 复制代码
// 基本数组解构赋值
const numbers = [1, 2, 3];
const [a, b, c] = numbers;
console.log(a); // 输出 1
console.log(b); // 输出 2
console.log(c); // 输出 3

// 交换变量的值
let x = 1;
let y = 2;
[x, y] = [y, x];
console.log(x); // 输出 2
console.log(y); // 输出 1

2. 对象解构赋值:

arduino 复制代码
// 基本对象解构赋值
const person = { name: 'John', age: 30 };
const { name, age } = person;
console.log(name); // 输出 'John'
console.log(age); // 输出 30

// 使用不同的变量名
const { name: personName, age: personAge } = person;
console.log(personName); // 输出 'John'
console.log(personAge); // 输出 30

ES6的解构赋值能够简化代码,使得从数组和对象中提取数据更加方便和直观。


ES6的对象简写

ES6引入了对象字面量的简写语法,使得在创建对象时更加简洁和方便。这种简写语法可以让我们更快速地定义对象,尤其在属性名和变量名一致的情况下非常实用。

1. 基本对象简写:

ini 复制代码
const name = 'John';
const age = 30;

// 使用变量名作为属性名
const person = { name, age };
console.log(person); // 输出 { name: 'John', age: 30 }

在这个例子中,我们使用变量 name 和 age 直接作为对象的属性名,而不需要再写成 { name: name, age: age } 的形式。


2. 方法简写:

javascript 复制代码
// 使用箭头函数作为方法
const person = {
  name: 'John',
  greet() {
    console.log('Hello, my name is ' + this.name);
  }
};

person.greet(); // 输出 "Hello, my name is John"

在这个例子中,我们可以直接在对象字面量中使用箭头函数来定义方法,而不需要再写成 greet: function() { ... } 的形式。


ES6展开运算符

ES6引入了展开运算符(Spread Operator),它是一种方便的语法,用于展开数组和对象。展开运算符可以在创建数组和对象、函数调用、数组拷贝等场景中非常有用。

1. 展开数组:

ini 复制代码
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5];
console.log(arr2); // 输出 [1, 2, 3, 4, 5]

在这个例子中,展开运算符...用于将arr1数组中的元素展开,然后将4和5添加到新数组arr2中。



2. 合并数组:

ini 复制代码
const arr1 = [1, 2, 3];
const arr2 = [4, 5];
const mergedArray = [...arr1, ...arr2];
console.log(mergedArray); // 输出 [1, 2, 3, 4, 5]

在这个例子中,我们使用展开运算符来合并两个数组,创建一个新的数组mergedArray。

3. 展开对象:

ini 复制代码
const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 };
console.log(obj2); // 输出 { a: 1, b: 2, c: 3 }

在这个例子中,展开运算符...用于将obj1对象中的属性展开,然后添加属性c到新对象obj2中。

对原没有影响


ES6模块化语法

私密不漏

导出export


导入 import


重名不怕

在ES6模块化语法中,可以使用as关键字给导入的模块成员(变量、函数、类等)进行重命名,以解决重名的问题。

例如,假设我们有两个模块 math.jsutils.js,它们都导出了一个名为 add 的函数:

javascript 复制代码
// math.js
export function add(a, b) {
  return a + b;
}

// utils.js
export function add(a, b) {
  return a + b;
}

在另一个模块中,我们可以使用as关键字给导入的函数进行重命名,以区分它们:

javascript 复制代码
import { add as mathAdd } from './math.js';
import { add as utilsAdd } from './utils.js';

console.log(mathAdd(2, 3)); // 输出:5
console.log(utilsAdd(2, 3)); // 输出:5

在上述示例中,我们通过as关键字将 math.js 中的 add 函数重命名为 mathAdd,将 utils.js 中的 add 函数重命名为 utilsAdd,以避免重名冲突。


依赖不乱

当一个模块依赖于其他模块时,可以使用import关键字引入所需的模块。通过指定模块的路径,可以将其他模块中导出的功能引入到当前模块中使用。

例如,假设我们有两个模块 math.jsutils.js,其中 math.js 导出了一个名为 add 的函数,而 utils.js 依赖于 math.js 中的 add 函数:

javascript 复制代码
// math.js
export function add(a, b) {
  return a + b;
}

// utils.js
import { add } from './math.js';

export function multiply(a, b) {
  return add(a, b) * 2;
}

在上述示例中,utils.js 使用import关键字引入了 math.js 中的 add 函数,并在 multiply 函数中使用了它。这样,utils.js 就解决了对 math.js 的依赖。

在另一个模块中,我们可以直接使用 utils.js 中导出的功能,而不需要关心它与 math.js 的依赖关系:

javascript 复制代码
import { multiply } from './utils.js';

console.log(multiply(2, 3)); // 输出:10

需要注意的是,模块之间的依赖关系应该通过import语句进行明确声明,以确保模块的正确加载顺序。这样可以确保在使用某个模块时,它所依赖的模块已经被正确加载和执行。


默认导出

javascript 复制代码
// math.js
export default function multiply(a, b) {
  return a * b;
}
javascript 复制代码
// main.js
import multiply from './math.js';

console.log(multiply(2, 3)); // 输出:6

总结

月色真美

相关推荐
&白帝&1 小时前
Vue.js 过渡 & 动画
前端·javascript
总是学不会.1 小时前
SpringBoot项目:前后端打包与部署(使用 Maven)
java·服务器·前端·后端·maven
Fanfffff7202 小时前
深入探索Vue3组合式API
前端·javascript·vue.js
光影少年2 小时前
node配置swagger
前端·javascript·node.js·swagger
昱禹2 小时前
关于CSS Grid布局
前端·javascript·css
啊QQQQQ2 小时前
HTML:相关概念以及标签
前端·html
就叫飞六吧3 小时前
vue2和vue3全面对比
前端·javascript·vue.js
Justinc.3 小时前
CSS基础-盒子模型(三)
前端·css
qq_2518364573 小时前
基于ssm vue uniapp实现的爱心小屋公益机构智慧管理系统
前端·vue.js·uni-app
._Ha!n.3 小时前
Vue基础(二)
前端·javascript·vue.js