ES6基础1-2(手写深拷贝、Vue数据劫持、Object.defineProperty...)

1.var都要改为let和const
  1. var声明的变量 (污染全局变量)
  2. 使用var导致变量提升的问题
  3. var可以被重复声明;let可以解决重复定义的问题
  4. var作用域的问题(全局作用域);let(函数作用域)
2.常见的作用域

全局作用域
函数作用域
块作用域{} + let

3.let

问题:暂存死区

let a = 100;
{
  console.log(a); //这里会报错:a is not defined
  //当前作用域有a,就不会去外面找;但是let不会变量提升,所以a在打印的时候还未被声明,不会是undefined
  let a = 200;
}
4.const 常量 不会变的量(地址不变即可)

const的值习惯性大写

const PI = { r: '3.14' };
PI.r = 3.15; // 此时不会报错,地址没有变

5.展开运算符...
  1. 数组和对象都可以使用
  2. ...只能拷贝一层,是浅拷贝
  3. 浅拷贝(拷贝之后还有关)
  4. 深拷贝(拷贝之后无关)
  5. Object.assign也是浅拷贝
6.不靠谱的深拷贝尝试:

我们可以把对象先转化成字符串 在把字符串转换成对象。会有一个问题,完全无法处理fn

Object.assign = ...
let school = {name:'zfpx',fn:function(){},aa:undefined,b:null,arr:[1,2,3,[4,5]]};
let my = {age:{count:18},name:'jw'};
let all = JSON.parse(JSON.stringify({...school,...my}));
my.age.count = 100;
console.log(all);
7.自己实现一个深拷贝方法(递归拷贝)

先掌握类型判断:

  • typeof
  • instanceof
  • Object.prototype.toString.call
  • constructor

小技巧:

  • [].constructor 返回一个 fn,即:Array();new Array()返回[]
  • {}.constructor 返回一个fn,即:Object();new Object()返回{}
  • new obj.constructor会返回一个[]或者{}

注意:

  • function直接返回;typeof function() {} == 'function'
  • Symbol不是对象,直接返回;typeof Symbol == 'function'
  • null == undefined true
  • 用weakMap来解决“循环引用”
function deepClone(obj, hash = new WeakMap()) {
  if (obj == null) return obj; // 判断obj是null还是undefined
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj);
  if (typeof obj !== 'object') return obj; // 不是对象就不用拷贝了
  if (hash.has(obj)) return hash.get(obj); // 如果weakmap中有对象就直接返回之前拷贝过得obj

  let cloneObj = new obj.constructor(); // 适配数组和对象
 // 如果是对象把他放到weakMap中,如果再拷贝这个对象这个对象就存在了,直接返回这个对象即可
  hash.set(obj, cloneObj);   // 防止循环调用问题,(程序会崩溃)

  for (let key in obj) {
    if (obj.hasOwnProperty(key)) { // for in会遍历出原型上的属性
      // 只拷贝私有属性,不考虑原型链上的属性
      // 如果赋予的值是对象 我就把这个对象放到weakmap中
      cloneObj[key] = deepClone(obj[key], hash); // 实现深拷贝
    }
  }

  return cloneObj;
}
8.set
  • set是集合;不能重复的东西,否则就白放了;没顺序
  • Set有symbol.iterator能被迭代,能被...展开
  • add,delete 添加和删除
  • 基础类型 string number boolean undefined object symbol ???
let s = new Set([1, 2, 3, 4, 1, 2, 3, 4]);
console.log(s); // Set { 1, 2, 3, 4 }
console.log(typeof s); // object
s.add('5');
s.delete('5');
let arr = [...s]; // 有迭代,才能被展开
console.log(arr); // [ 1, 2, 3, 4 ]

集合:并集、交集、差集

let s01 = [1, 2, 3, 1, 2, 6];
let s02 = [3, 4, 5, 1, 2];

// 并集:
function union() {
  let s1 = new Set(s01);
  let s2 = new Set(s02);
  console.log([...new Set([...s1, ...s2])]);
}
union(); // [ 1, 2, 3, 6, 4, 5 ]

// 交集:
function intersection() {
  return [...new Set(s01)].filter(function (item) {
    // filter返回true表示留下
    return new Set(s02).has(item);
  });
}
console.log(intersection()); // [ 1, 2, 3 ]

// 差集: 要看谁差谁,顺序不同结果也不同
function diff() {
  return [...new Set(s01)].filter(function (item) {
    return !new Set(s02).has(item); // 跟intersection相比就加了一个!
  });
}
console.log(diff()); // [6]
9.Map
  • map 映射表
  • 跟set唯一的不同是:map有key。
  • map也不能放重复的
  • 在Map里销毁obj,有引用关系。
let m = new Map(); 
m.set('name', '123');
m.set('name', '111');
let obj = { age: 1 };
m.set(obj, '123');
m.set(obj, '456'); // 这个obj的引用的空间被set所引用
obj = null; // 把obj清空,但是这个空间还是在的
console.log(m.obj); // undefined
console.log(m); // Map { 'name' => '123', { age: 1 } => '456' }
10.WeakMap
  • WeakMap的key,必须是对象类型,否则会报错:Invalid value used as weak map key;
  • 作为对象key的对象,其应用关系会被销毁掉。
  • 在WeakMap里可以销毁obj,因为没有引用关系,也不会再引用原来的对象。
let m = new WeakMap(); 
let obj = { age: 1 };
m.set(obj, '123');
obj = null; // 把obj清空,但是这个空间还是在的
console.log(m.obj); // undefined
console.log(m); // WeakMap { <items unknown> }
11.weakMap和Map的区别(与回收机制有关
  1. weakMap是弱链接,可以清空,对象删除了也不会有引用关系。
  2. Map即便删除了,还是会有引用关系,会继续占用空间,不会被销毁。
12.Object.defineProperty

ES5语法,使用场景很多:vue,react...

  • 通过Object.defineProperty定义属性,可以增加拦截器;
  • 定义的属性是隐藏属性,不可枚举,不能用for...in遍历到。
  • 通过Object.defineProperty定义属性 可以增加拦截器
  • 只能用在对象上,数组是不行的
let obj = {};
let other = '';
// 不可枚举 函数的原型 Array.protoype
Object.defineProperty(obj, 'name', {
  enumerable: true, // 是否可以枚举
  configurable: true, // 是否可以配置: 能不能删除这个属性
  //writable:true, // 是否可以重写
  get() { // 读取方法
    console.log('----');
    return other;
  },
  set(val) {  // 设置方法
    other = val;
  }
});
// delete obj.name;  // 如果configurable为false,那么会删不掉对象的属性
obj.name = 456;
console.log(obj.name);  // 456
13.对象的setter和getter(Vue中的数据双向绑定)
let obj = {
  other: '123',
  get name() {
    return this.other;
  },
  set name(val) {
    this.other = val;
  }
};
obj.name = 456;
console.log(obj.name);
14.vue的数据劫持 (把所有的属性都改成 get和set方法)
function update() {   // 模拟的更新方法
  console.log('更新视图');
}
let data = {
  name: 'zfpx',
  age: 18,
  address: {
    location: '回龙观'
  }
};
function observer(obj) {
  // Object.defineProperty只能用在 对象上 (数组也不识别)
  if (typeof obj !== 'object') return obj;
  for (let key in obj) {
    defineReactive(obj, key, obj[key]);
  }
}
// 定义响应式
function defineReactive(obj, key, value) {
  observer(value); // 递归,嵌套的数据也会被观测到
  Object.defineProperty(obj, key, {
    get() {
      return value;
    },
    set(val) {
      if (val !== value) {
        observer(val);
        update();
        value = val;
      }
    }
  });
}
observer(data);
data.address = [1, 2, 3];
let methods = ['push', 'slice', 'pop', 'sort', 'reverse', 'unshift'];
methods.forEach((method) => {
  // 面相切片开发 装饰器
  let oldMethod = Array.prototype[method];
  Array.prototype[method] = function () {
    update();
    oldMethod.call(this, ...arguments);
  };
});
data.address.push(4);
data.address.push(4);
15.箭头函数
  • 没有this,没有arguments
  • 53min开始举的this例子没看懂???
  • obj是一个对象,不是作用域,也就没有this
  • let声明的变量,不属于window属性;属于自己window下的作用域???
let a = 1;
let obj = { //obj是一个对象,不是作用域
  a: 2,
  fn: () => {
    setTimeout(() => {
      console.log(this.a); // undefined
      // 因为定时器是window在调用,let的a不会挂载到window上
    });
  }
};
obj.fn();
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343