小宋爱睡觉 小宋爱睡觉
首页
  • HTML
  • CSS
  • JavaScript
  • Vue
  • React
  • 计算机网络
  • 浏览器原理
  • 性能优化
  • 设计模式
手写系列
  • 字符串
  • 数组
  • 链表
  • 树
  • 动态规划
  • 排序算法
  • GitHub (opens new window)
  • JueJin (opens new window)
首页
  • HTML
  • CSS
  • JavaScript
  • Vue
  • React
  • 计算机网络
  • 浏览器原理
  • 性能优化
  • 设计模式
手写系列
  • 字符串
  • 数组
  • 链表
  • 树
  • 动态规划
  • 排序算法
  • GitHub (opens new window)
  • JueJin (opens new window)
  • 数据类型
  • ES6
    • let const var 区别
    • const对象的属性可以修改吗
    • 可不可以new一个箭头函数出来? new操作符做了什么?
    • 箭头函数和普通函数的区别
    • 介绍一下Proxy
  • JS基础
  • 执行上下文/ 闭包/ 作用域链
  • 原型和原型链
  • 情景题
  • JavaScript
Crucials
2021-11-28

ES6

# ES6

# let const var 区别特别重要

  • let const具有块级作用域 var不存在块级作用域

    • 解决了内层变量覆盖外层、用来计数的循环变量泄露为全局变量的问题
  • var存在变量提升 let const不存在变量提升

  • 浏览器的全局对象是window Node的全局对象是global var在最外层声明的是全局变量 为该变量添加为全局对象的属性 但是let const不会

  • var允许重复声明 后声明的会覆盖前面的 const let不允许重复声明

  • 暂时性死区 在使用let const声明变量之前 变量不可用 在语法上成为 暂时性死区 var不存在暂时性死区

  • let可以更改指针的指向 const不能更改指针的指向

    • 初始值设置 var let可以不用设置初始值 而const声明必须设置初始值
区别 var let const
是否有块级作用域 × ✔️ ✔️
是否存在变量提升 ✔️ × ×
是否添加全局属性 ✔️ × ×
能否重复声明变量 ✔️ × ×
是否存在暂时性死区 × ✔️ ✔️
是否必须设置初始值 × × ✔️
能否改变指针指向 ✔️ ✔️ ×

# const对象的属性可以修改吗重要

const保证的是指向的内存地址不改变,对于基本类型的数据(number string boolean),他就是指向那个内存地址

但是引用类型不同(array object)变量指向数据的内存地址 保存的只是一个指针 至于他指向的数据结构是不是可变的就不能控制了

# 可不可以new一个箭头函数出来? new操作符做了什么?特别重要

箭头函数是ES6提出的 没有prototype 没有自己this指向 更没有arguments参数 所以不能new一个箭头函数出来

new操作符做了以下几个步骤

var obj  = {};
obj.__proto__ = F.prototype;
F.call(obj);
1
2
3
  1. 创建一个对象

  2. 将构造函数的作用域赋值给新对象 (将对象的__proto__属性指向构造函数的prototype属性)

  3. 将构造函数的this替换到新对象 然后调用 (也就是将属性和方法加入到this引用的对象里)

  4. 隐式返回this(返回新的对象)

实现一个new

// 上面的三部代码为核心代码 那么还有其他的情况
// 来看一个栗子

function Otaku (name, age) {
    this.strength = 60;
    this.age = age;

    return {
        name: name,
        habit: 'Games'
    }
}

var person = new Otaku('shm', '18');

console.log(person.name) // shm
console.log(person.habit) // Games
console.log(person.strength) // undefined
console.log(person.age) // undefined

// 我们这里返回了一个对象 在函数里面我们指定了strength和age的值 但是new出来却是undefined ,说明在实例中只能访问返回的对象中的属性

// 还有一个栗子
// 假如返回的是基本类型的值呢

function Otaku (name, age) {
    this.strength = 60;
    this.age = age;

    return 'say something'
}

var person = new Otaku('Kevin', '18');

console.log(person.name) // undefined
console.log(person.habit) // undefined
console.log(person.strength) // 60
console.log(person.age) // 18
// 跟上面截然相反 有返回值但是没有处理 所以我们要判断一下返回值是不是对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
function objFactory() {
  let newObj = Object.create(null);

  // 取出参数的第一位
  let constructor = Array.prototype.shift.call(arguments);
  // result为返回值
  let result = null;
  // 判断是不是一个函数
  if (typeof constructor !== "function") {
    console.error("type error");
    return;
  }

  // 新建一个空对象 对象原型为构造函数的prototype对象
  newObj.__proto__ = constructor.prototype;
  // 将this指向新建对象并调用
  result = constructor.apply(newObj, arguments);
  // 返回对象
  // 这里还要看看构造函数的返回值是不是基本类型的值 还是对象或者函数

  return typeof result === "object" ? result : newObj;
}

function Otaku(name, age) {
  this.strength = 60;
  this.age = age;

  return {
    name: name,
    habit: "Games",
  };
}

let temp = objFactory(Otaku, "shm", "20");
console.log(temp.name); // shm
console.log(temp.habit); // Games
console.log(temp.strength); // undefined
console.log(temp.age); // undefined
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

# 箭头函数和普通函数的区别

  • 箭头函数比普通函数更简洁

  • 箭头函数没有自己的this

    • 在自己作用域的上一层继承this
  • this指向永远不变

var id = 'GLOBAL';
var obj = {
  id: 'OBJ',
  a: function(){
    console.log(this.id);
  },
  b: () => {
    console.log(this.id);
  }
};
obj.a();    // 'OBJ'
obj.b();    // 'GLOBAL'
new obj.a()  // undefined
new obj.b()  // Uncaught TypeError: obj.b is not a constructor
1
2
3
4
5
6
7
8
9
10
11
12
13
14

call bind apply 不能改变this的指向

var id = 'Global';
let fun1 = () => {
    console.log(this.id)
};
fun1();                     // 'Global'
fun1.call({id: 'Obj'});     // 'Global'
fun1.apply({id: 'Obj'});    // 'Global'
fun1.bind({id: 'Obj'})();   // 'Global'
1
2
3
4
5
6
7
8
  1. 不能作为构造函数使用

  2. 没有自己的arguments

  3. 用的是外层函数的arguments

  4. 没有prototype

  5. 不能用于Generator函数 不能用yield关键字

# 介绍一下Proxy

let p = new Proxy(target, handler)
// target代表需要添加代理的对象 handler用来自定义对象中的操作 比如get set
1
2

实现一个数据响应式

let onWatch = (obj, setBind, getLogger) => {
  let handler = {
    // 这里的receier是改变this的指向的作用
    get(target, property, receiver) {
      getLogger(target, property)
      return Reflect.get(target, property, receiver)
    },
    set(target, property, value, receiver) {
      setBind(value, property)
      return Reflect.set(target, property, value)
    }
  }
  return new Proxy(obj, handler)
}
let obj = { a: 1 }
let p = onWatch(
  obj,
  (v, property) => {
    console.log(`监听到属性${property}改变为${v}`)
  },
  (target, property) => {
    console.log(`'${property}' = ${target[property]}`)
  }
)
p.a = 2 // 监听到属性a改变
p.a // 'a' = 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
上次更新: 2022/03/20, 19:40:28
数据类型
JS基础

← 数据类型 JS基础→

Copyright © 2021-2025 粤ICP备2021165371号
  • 跟随系统
  • 浅色模式
  • 深色模式