image frame

buynonsense

思维导图:mindmap

普通函数和箭头函数的this绑定问题

在JavaScript中,理解this的绑定机制是非常重要的,尤其是在普通函数和箭头函数中this的行为差异。这两种函数类型对this的处理方式有本质的不同。

普通函数的this

普通函数(包括函数声明、函数表达式、以及通过Function构造函数创建的函数)的this绑定主要取决于函数的调用方式。这里有几种不同的情况:

  1. 全局上下文或者函数调用:在非严格模式下,普通函数的this指向全局对象(在浏览器中是window,在Node.js中是global);在严格模式下(使用'use strict'),this的值为undefined

    1
    2
    3
    4
    function normalFunction() {
    console.log(this);
    }
    normalFunction(); // 在浏览器中打印window,在Node.js中打印global或者在严格模式下为undefined
  2. 方法调用:当函数作为对象的方法被调用时,this指向该方法所属的对象。

    1
    2
    3
    4
    5
    6
    const obj = {
    method: function() {
    console.log(this);
    }
    };
    obj.method(); // 打印obj
  3. 构造函数调用:使用new关键字调用函数时,this将指向新创建的对象。

    1
    2
    3
    4
    function Constructor() {
    console.log(this);
    }
    new Constructor(); // Constructor的一个新实例
  4. applycallbind方法:这些方法可以显式地设置函数调用的this值。

    1
    2
    3
    4
    function show() {
    console.log(this);
    }
    show.call({a: 1}); // {a: 1}

箭头函数的this

箭头函数(使用=>语法定义的函数)对this的处理完全不同。箭头函数不绑定自己的this,而是捕获其所在上下文的this值作为自己的this值,这种行为也被称为“词法作用域”或“静态作用域”。因此,箭头函数内部的this值是在定义它时确定的,而不是在调用时。

1
2
3
4
5
6
7
8
9
const obj = {
method: function() {
const arrowFunc = () => {
console.log(this);
};
arrowFunc();
}
};
obj.method(); // 打印obj

在上面的例子中,arrowFunc箭头函数捕获了method方法中的this(即obj对象),而不管它在哪里被调用。

总结

  • 普通函数的this绑定取决于函数的调用方式,可以是全局对象、当前对象、新创建的对象,或者是通过applycallbind方法显式指定的对象。
  • 箭头函数不绑定自己的this,它会捕获其定义时所处的上下文中的this值,并将其用作自己的this值。

默认导出命名导出

在JavaScript中,从模块导入时使用大括号{}与不使用大括号主要涉及到两种不同的导出/导入方式:默认导出(Default exports)和命名导出(Named exports)。

默认导出(Default Export)

当一个模块只导出一个值或者一个对象时,可以使用默认导出。这时,导入时不需要使用大括号。例如,如果App.vue文件默认导出了一个Vue组件,那么你可以这样导入它:

1
import App from './App.vue'

这里,App是你自己命名的,它指向了App.vue文件的默认导出内容。

命名导出(Named Export)

如果一个模块导出了多个值或对象,那么它们应该使用命名导出。导入这些值或对象时,需要使用大括号来指定你想要导入的具体名称。例如,如果vue模块有一个命名导出createApp,你需要这样导入它:

1
import { createApp } from 'vue'

这里,createApp必须与vue模块中导出的名称完全匹配。

总结

  • 没有大括号:用于默认导出,导入时可以自由命名。
  • 有大括号:用于命名导出,导入时必须使用模块中定义的名称。

这种设计允许模块以灵活的方式导出一个或多个值,同时也让导入这些值的方式更加明确和严格。

浏览器同源策略

浏览器的同源策略(Same-Origin Policy,SOP)是一种重要的安全策略,用于限制一个源(origin)中加载的文档或脚本如何与另一个源的资源进行交互。它是一个关键的安全机制,用于防止恶意网站读取或修改另一个网站的数据而不被用户授权。

一个源的定义包括三个部分:协议(protocol)、域名(domain),和端口(port)。只有当这三者全部匹配时,两个URL才属于同一个源。例如,http://example.com/page1http://example.com/page2 属于同一个源,因为它们的协议、域名和端口都相同。但是,http://example.comhttps://example.com 就不属于同一个源,因为它们的协议不同。

同源策略限制了以下几种行为:

  1. Cookie、LocalStorage 和 IndexDB 的访问:网站不能访问不同源的数据存储。
  2. DOM 节点:一个源中的脚本不能访问另一个源的文档内容。
  3. AJAX 请求:通过 XMLHttpRequest 或 Fetch 发起的跨源 HTTP 请求会受到限制。

尽管同源策略限制了跨源访问,但现代Web开发中经常需要跨域资源共享(CORS,Cross-Origin Resource Sharing)。CORS 是一种机制,它允许网页的脚本能够向不同源的服务器发出请求,前提是服务器在响应中包含了适当的 CORS 头信息,表明它允许来自请求源的访问。

例如,如果一个网页尝试通过 AJAX 请求访问另一个域名下的API,那么API服务器需要在响应头中包含如下字段之一,以允许跨源请求:

1
Access-Control-Allow-Origin: *

或者指定允许的源:

1
Access-Control-Allow-Origin: http://example.com

同源策略是Web安全的基石之一,它帮助保护用户信息免受跨站点脚本攻击(XSS)和其他类型的网络攻击。

函数引用vs函数调用

在 Vue 中

函数调用(Function Invocation)

当你在函数名后面加上括号 (),如 function(),这代表你正在调用这个函数。这意味着你希望这个函数立即执行,并返回执行结果。如果这样的代码出现在组件的模板或者是在组件的某些生命周期钩子中,它将在这些地方被立即执行。例如,在组件被初始化时,如果你在 created 钩子中调用了 function(),那么这个函数会在组件创建的过程中被执行。

函数引用(Function Reference)

当你仅仅提供函数名,不加括号,如 function,这代表你在提供一个对这个函数的引用。这意味着你并不是在调用这个函数让它立即执行,而是在告诉 Vue 或者其他代码,“这里有一个函数,当满足某些条件时,请你去调用它。”这种方式常见于事件监听或者将函数作为参数传递给其他函数的场景。例如,在模板中绑定事件监听时,你可能会这样写:@click="function",这告诉 Vue,当点击事件发生时,调用 function

总结

  • 函数调用 (function()) 是指立即执行该函数。
  • 函数引用 (function) 是指提供一个函数的引用,以便将来某个时刻调用。

这个概念在很多编程语言和框架中都非常重要,因为它涉及到如何控制函数的执行时机。在 Vue 中,正确地使用这两种方式对于事件处理、生命周期钩子的使用等都至关重要。

传递Token携带Bearer前缀

1
2
3
return request.get('/category',{headers:{'Authorization':`Bearer ${tokenStore.token}`}})

return request.get('/category',{headers:{'Authorization':tokenStore.token}})

区别

这两者之间的区别在于'Authorization'头部中的值。

  1. 第一个示例中:

    使用了模板字符串插值,这是ES6引入的一种新的字符串表示方法。将BearertokenStore.token连接在一起。这个形式通常用于在发送请求时将令牌(token)放置在'Authorization'头部中。这是一种常见的做法,尤其是在使用JWT(JSON Web Tokens)进行身份验证时。

  2. 第二个示例中:

    这里的tokenStore.token是令牌本身,没有添加额外的前缀,如Bearer。这种方式通常用于特定类型的后端需要的身份验证标准。有些后端可能不需要前缀Bearer,而是直接使用令牌本身来验证请求。

总的来说,取决于你的后端服务器如何设置接收身份验证信息。一些后端可能要求你在令牌前添加Bearer前缀,而其他后端可能只需令牌本身即可。所以,你需要根据你的后端服务器的需求来决定如何在请求头部中设置'Authorization'的值。

好处

将令牌放置在Authorization头部中时,使用Bearer前缀的主要好处在于安全性和标准化。

  1. 安全性: 使用Bearer前缀可以帮助服务器更容易地辨别令牌类型。这样,服务器可以知道接收到的令牌是使用Bearer身份验证方案生成的,从而可以相应地处理它。这种清晰的标识有助于防止恶意攻击者尝试使用不同类型的令牌来进行欺骗或攻击。

  2. 标准化: Bearer前缀是OAuth 2.0标准中定义的一部分,它规范了使用令牌进行身份验证的过程。这种标准化有助于确保不同系统之间的互操作性和兼容性。如果你的应用程序或API遵循OAuth 2.0标准,那么使用Bearer前缀就是符合标准的一部分。

总的来说,虽然Bearer前缀对于所有情况都不是必需的,但它提供了一种更安全和标准化的方式来传递令牌,并且使得服务器能够更轻松地处理令牌的验证和授权。

push() 和 append()

在Vue.js中,.push().append() 是用于向数组添加新元素的两种不同方法。下面是它们的解释和用法:

  1. **.push()**:

    • .push() 方法是 JavaScript 中 Array 对象的一个方法,用于在数组的末尾添加一个或多个元素,并返回修改后的数组的长度。
    • 在Vue.js中,如果你有一个响应式的数组(即使用了Vue的响应式系统进行绑定),你可以使用 .push() 方法向数组添加新元素,Vue将自动更新视图以反映数组的变化。
    • 示例:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      // 假设有一个Vue实例
      new Vue({
      data: {
      items: [1, 2, 3]
      },
      methods: {
      addItem() {
      this.items.push(4); // 向items数组末尾添加一个新元素4
      }
      }
      });
  2. **.append()**:

    • .append() 方法通常用于 DOM 操作,用于向指定元素的末尾添加一个或多个新的子节点、HTML元素或文本节点。
    • 在Vue.js中,.append() 方法并不是原生的Vue.js方法,而是DOM操作方法之一,用于直接修改DOM结构,而不会影响Vue响应式系统。
    • 示例:
      1
      2
      3
      4
      5
      // 假设有一个包含id为“list”的ul元素
      let ul = document.getElementById('list');
      let li = document.createElement('li');
      li.textContent = 'New Item';
      ul.append(li); // 向ul元素的末尾添加一个新的li子元素

综上所述,.push() 用于向Vue响应式数组中添加新元素,而 .append() 则用于直接向DOM元素的末尾添加新的子节点或元素。在Vue.js中,通常更推荐使用 .push() 来添加新元素,以便利用Vue的响应式系统来自动更新视图。

MySQL5转MySQL8

将Windows 10上的MySQL 5升级到MySQL 8并保留数据库中的数据,可以通过以下步骤来完成:

1. 备份数据

首先,确保备份你的数据库。这是升级过程中最重要的一步,以防万一出现问题,你可以恢复到升级前的状态。

使用mysqldump工具备份所有数据库:

win+r打开cmd输入

1
mysqldump -u root -p --all-databases > all_databases.sql

然后输入MySQL的root用户密码,将会把所有数据库导出到all_databases.sql文件中。并且这个文件会储存到当前cmd的路径下(默认是C:\user\xxx)

2. 卸载MySQL 5 (非必须)

  • 打开“控制面板” > “程序和功能”,找到MySQL 5,然后选择“卸载”。
  • 删除MySQL 5的安装目录,通常位于C:\Program Files\MySQL\MySQL Server 5.x
  • 删除MySQL的数据目录,如果你在安装时没有更改默认位置,它通常位于C:\ProgramData\MySQL\MySQL Server 5.x\Data注意:请确保你已经备份了数据。

3. 安装MySQL 8

  • 从MySQL官网下载MySQL 8的Windows安装程序。从MySQL官网下载8版本的zip包
  • 运行安装程序,选择“Custom”安装类型以自定义安装选项。 ..\mysql-8.0.32-winx64\bin 路径写入到环境变量path中
  • 在安装过程中,安装程序可能会提示你配置一些选项,包括服务器类型、默认字符集、网络配置等。根据你的需求进行选择。
  • 设置root用户的密码。请记住这个密码,因为你稍后需要它来恢复数据库。

3.1 停止MySQL 5服务(管理员cmd)

  • net stop mysql
    
    1
    2
    3
    4
    ### 3.2 从服务(windows那个服务)中删除MySQL5

    - ```shell
    sc delete mysql

3.3 启动MySQL8

  • 在..\mysql-8.0.32-winx64\bin目录下进入cmd

  • mysqld --install
    net start mysql
    
    1
    2
    3
    4
    5

    ### 4. 恢复数据
    使用`mysql`命令行工具恢复之前导出的数据库:
    ```shell
    mysql -u root -p < all_databases.sql
    这将提示你输入MySQL的root用户密码,然后从`all_databases.sql`文件中恢复所有数据库。

你也可以用SQLyog、Navicat等工具从备份文件导入进MySQL8

5. 升级后的检查

  • JDBC驱动添加cj等事项

JS和TS区别

JavaScript和TypeScript是两种用于Web开发的编程语言。JavaScript是一种动态类型语言,而TypeScript是JavaScript的静态类型超集。

类型系统

JavaScript是一种动态类型语言,这意味着变量的类型在声明时不需要指定,并在运行时确定。这使得JavaScript代码更加灵活,但也更容易出现类型错误。

TypeScript是一种静态类型语言,这意味着变量的类型必须在声明时指定。这有助于在编译时捕获类型错误,从而提高代码的质量。

静态分析

TypeScript支持静态分析,这是一种在代码运行之前分析代码以查找潜在错误的技术。静态分析可以帮助开发人员在代码发布之前发现错误,从而提高代码的质量。

JavaScript不支持静态分析,这意味着开发人员必须在代码运行时才能发现错误。这可能会导致代码发布后出现错误,从而影响用户体验。

生态系统

JavaScript拥有庞大的生态系统,包括大量的库和框架。这使得开发人员可以轻松找到满足其需求的工具。

TypeScript的生态系统正在快速增长,但仍不及JavaScript的生态系统庞大。

适用场景

JavaScript适用于小型项目、原型开发或那些不需要强类型约束的应用程序。

TypeScript适用于大型项目、需要强类型约束的应用程序或需要使用静态分析的应用程序。

总结

JavaScript和TypeScript是两种各有优势的编程语言。JavaScript更加灵活,适用于快速开发和原型验证。TypeScript更加安全,适用于大型项目和需要强类型约束的应用程序。

具体的区别:

特性 JavaScript TypeScript
类型系统 动态类型 静态类型
静态分析 不支持 支持
生态系统 庞大 正在快速增长
适用场景 小型项目、原型开发、不需要强类型约束的应用程序 大型项目、需要强类型约束的应用程序、需要使用静态分析的应用程序

使用TypeScript的优势:

  • 可以提高代码的质量,减少类型错误。
  • 可以提高代码的可维护性,使代码更容易理解和修改。
  • 可以提高代码的开发效率,减少开发人员的工作量。

以下是一些使用TypeScript的劣势:

  • 学习曲线较陡,需要开发人员掌握新的语法和概念。
  • 代码量会增加,因为需要添加类型注解。
  • 可能会出现兼容性问题,因为TypeScript代码需要编译成JavaScript才能运行。

解构props对象

解构 props 对象

解构 props 对象是一种在接收组件属性(props)时,从 props 对象中提取出一个或多个属性的技术。这是 JavaScript中的解构赋值(destructuring assignment)特性的一个应用,允许你在较少的代码中直接访问对象内 的属性。在Vue组件中使用时,这种方式可以让你更方便地访问和使用传递给组件的属性。

在Vue组件中解构 props

的方式 当你在Vue组件中定义 props时,通常会接收一个 props对象,这个对象包含了父组件传递给子组件的所有属性。运 过解构,你可以直接在组件的setup 函数中或其他地方提取出你需要的属性,而不是每次都通过props 访问。

示例

假设有一个子组件,父组件会向它传递 title 和 description 两个属性:

1
2
3
export default {
props: ['title', 'description']
}

在子组件中,可以使用解构赋值来提取这两个属性:

1
2
3
4
5
6
7
8
9
10
setup(props) {
const { title, description } = props;

console.log(title, description);

return {
title,
description
}
}

通过解构,我们可以直接在 setup 函数中使用 title 和 description 变量,而不用每次都通过 props.title 和 props.description 来访问。

注意事项

  • 解构 props 时要注意,解构出来的变量不会是响应式的。如果props 的属性在父组件中发生变化,那么解构出 的变量不会自动更新。如果需要保持响应性,可以使用Vue的 toRefs 函数来解构响应式对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { toRefs } from 'vue';

export default {
props: ['title', 'description']
}

setup(props) {
const { title, description } = toRefs(props);

console.log(title, description);

return {
title,
description
}
}
  • 解构赋值使得代码更简洁,但在使用时应当注意其对响应性的影响,特别是在需要响应父组件变化的场景中。

通过解构 props 对象,你可以更简洁、直观地访问和使用组件的属性,这在处理具有多个属性的组件时尤其有用。

ref产生RefImpl对象

ref形式调用某个变量的值需要.value,如果直接调用实际上是访问的一个RefImpl对象

当你使用 ref 创建一个响应式引用但在访问或操作时忘记添加 value,实际上你访问的是一个 RefImpl 对象,而不是该引用所持有的值。RefImpl 对象是 Vue 内部用于实现响应式行为的对象,它包含了响应式引用的元数据和值。

例如,如果你创建了一个:

1
const count = ref();

如果直接使用 count 而不是 count.value:

1
console.log(count);

这时,你不会得到 count 的值,而是得到一个包含 value 属性的 RefImpl 对象。这个对象大概长这样:

1
2
3
{
value: ...
}

因此,直接访问创建的变量而不使用 value,你得到的是一个 Vue 的内部响应式对象,而不是你存储在其中的值。这通常不是你想要的结果,因为你通常需要操作这个值本身,而不是包裹它的对象。

Q:

在使用 ref 下,虽然说我们使用的是基本数据类型,但是在 Vue 中会把它转换成一个对象吗?然后通过“对象.value”获取这个对象的值。

A:

是的。在 Vue 3 中,当你使用 ref 来处理基本数据类型(如字符串、数字等)时,Vue 实际上会将这个基本数据类型包装在一个对象中。这个对象是一个响应式的引用类型,通常称为 RefImpl 对象,它包含一个 value 属性,该属性持有你想要存储的实际数据。

这样做的目的是让基本数据类型也能够享受 Vue 的响应式系统的好处。在 Vue 的响应式系统中,对象和数组可以被直接转换为响应式对象,但基本数据类型不能直接变成响应式的,因为它们不是对象。通过将基本数据类型包装在一个对象中,Vue 可以监视这个对象的 value 属性的变化,从而实现对基本数据类型的响应式处理。

这就是为什么你需要通过 value 来访问或修改 ref 引用的值,这个设计允许 Vue 跟踪对这个值的所有读取和写入操作,确保当数据变化时,视图能够自动更新。

下面是一个简单的例子来说明这个过程:

1
2
3
4
5
6
7
8
9
import { ref } from 'vue';

const count = ref(0);

console.log(count.value); // 输出 0

count.value = 1;

console.log(count.value); // 输出 1

在这个例子中,count 是一个响应式引用对象,它包裹了一个基本数据类型(数字)。通过 count.value,你可以访问和修改这个数字,而 Vue 会确保任何依赖于 count 的视图都会在 count.value 变化时自动更新。

  • Copyrights © 2015-2024 buynonsense
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信