• 【JavaScript进阶之旅 ES6篇 第十章】操作原型的方法、super、4种遍历方式、Symbol


    一、操作原型的方法

    function Person(name, age) {
    	this.name = name;
    	this.age = age;
    }
    
    const person = new Person();
    
    console.log(person.__proto__); // {constructor: f Person(){}}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    1、person.proto = {}

    • 不推荐这样修改

    原因:

    1. 他具有语义化,因为他是一个内部属性,原则上不允许修改
    2. 访问效率慢
    3. 所有继承到该原型的对象都会影响的到

    2、操作原型的方法

    Object.setPrototypeOf()

    • 写的操作
    • 参数:
      1. 目标对象
      2. 指定的原型
    • 返回值:目标对象的引用
    let proto = {
    	x: 20,
    	y: 30
    }
    
    let obj = {
    	z: 40
    }
    
    let obj1 = Object.setPrototypeOf(obj, proto);
    
    console.log(obj);
    /**
     * {
     * 	z: 40,
     * 	[[prototype]]: Object
     * 			x: 20,
     * 			y: 30
     * }
     */ 
    console.log(obj === obj1); // true
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 第一个参数为:有包装类的原始值,不会有任何效果,只会将第一个参数进行包装类包装后返回
    // 1 -> 经过Number包装类 -> 打印的是Number上的原型,默认是0
    let obj = Object.setPrototypeOf(1, {a: 1});
    
    console.log(obj); // 1
    
    console.log(Object.getPrototypeOf(obj)); // Number{0}
    
    console.log(Object.getPrototypeOf(Number(1)) === Number.prototype); // true
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    同理,string跟boolean也会失效:

    let obj = Object.setPrototypeOf('1', {a: 1});
    
    console.log(obj); // '1'
    
    console.log(Object.getPrototypeOf(obj)); // String{''}
    
    
    
    let obj2 = Object.setPrototypeOf(true, {a: 1});
    
    console.log(obj2); // true
    
    console.log(Object.getPrototypeOf(obj)); // Boolean{false}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 第一个参数为:没有包装类的原始值undefined或null会报错
    let obj = Object.setPrototypeOf(undefined, {a: 1}); // 报错
    
    let obj2 = Object.setPrototypeOf(null, {a: 1}); // 报错
    
    • 1
    • 2
    • 3

    Object.getPrototypeOf()

    • 读取操作

    Object.create(obj)

    • 生成操作

    二、Object.keys()|.values()|.entries()

    1. Object.keys()

      • 返回对象自身的可枚举属性的键名,不含继承属性
      • 参数:目标对象
    2. Object.values()

      • 返回对象自身可枚举属性的键值,不含继承属性
      • 参数:目标对象
      • Object.entries()
      • 返回对象自身可枚举属性的键名键值的二维数组
      • 参数:目标对象
    const foo = {
    	a: 1,
    	b: 2, 
    	c: 3
    }
    
    Object.defineProperties(foo, {
    	d: {
    		value: 4,
    		enumerable: true
    	},
    	e: {
    		value: 5,
    		enumerable: false
    	}
    });
    
    // 返回对象可枚举的属性的键名
    console.log(Object.keys(foo)); // (4) ['a', 'b', 'c', 'd']
    // 返回对象可枚举的属性的键值
    console.log(Object.values(foo)); // (4) [1, 2, 3, 4]
    console.log(Object.entries(foo));
    // [
    //     [
    //         "a",
    //         1
    //     ],
    //     [
    //         "b",
    //         2
    //     ],
    //     [
    //         "c",
    //         3
    //     ],
    //     [
    //         "d",
    //         4
    //     ]
    // ]
    
    • 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
    • 40
    • 遍历对象时,会通过相应的包装类对象
    let obj = {};
    Object.keys(obj); // []
    
    let obj = 1;
    Object.keys(obj); // []
    
    let obj = true;
    Object.keys(obj); // []
    
    let obj = '123';
    Object.keys(obj); // ['0', '1', '2']
    
    // values()跟entries()方法同理
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    三、super

    • super指的是是对象上的原型对象

    只有在对象方法的简写中才能生效⭐

    let proto = {
    	x: 20,
    	y: 30,
    	bar: function() {
    		return this.y;
    	}
    }
    
    let obj = {
    	z: 40,
    	foo() {
    		return super.bar();
    	}
    }
    
    Object.setPrototypeOf(obj, proto);
    
    console.log(obj.foo()); // 30
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    四、Symbol()

    什么是Symbol()

    • ES6新增的基本数据类型(原始类型)
    • Symbol()不是构造函数,只是函数而已,不可以实例化(new)

    为了解决对象属性的重名问题

    let s1 = Symbol;
    
    console.log(s1); // ƒ Symbol() { [native code] }
    
    
    • 1
    • 2
    • 3
    • 4

    1、特点

    • 是原始类型的值
    • 所有的Symbol()值都不一样,不相等
    • 他是通过传入的标识符来识别
    • 不能添加属性
    let s1 = Symbol(),
    		s2 = Symbol();
    
    console.log(s1, s1); // Symbol()  Symbol()
    console.log(s1 === s2); // false
    console.log(typeof s1); // symbol
    
    s1.a = 1;
    console.log(s1.a); // undefined
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2、Symbol不能通过隐式转换,只能通过显示转换

    const obj = {
    	a: 1
    }
    
    let a1 = Symbol(obj); 
    console.log(a1); // Symbol([object Object])
    
    console.log(Symbol(undefined)); // Symbol()
    
    // 通过Object.prototype.toString()转换
    console.log(Symbol(null)); // Symbol(null)
    
    // console.log(Symbol() + 1); // 报错
    // console.log(Symbol() + '1'); // 报错
    
    
    // Symbol只有Number不能转,String跟Boolean是可以的
    // console.log(Number(a1)); // 报错
    
    // Symbol不可以通过隐式转换,只能通过显示转换
    // console.log(a1 + ''); // 报错
    console.log(String(a1)); // Symbol([object Object])
    
    console.log(Boolean(a1)); // true
    console.log(!a1); // false
    
    console.log(Object.getPrototypeOf(a1));
    
    
    
    • 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

    3、Symbol.toString()

    let obj = null;
    let s1 = Symbol(obj);
    
    console.log(s1.toString()); // 'Symbol(null)'
    
    • 1
    • 2
    • 3
    • 4

    4、在对象中使用Symbol

    let name = Symbol();
    let person = {};
    
    // 使用defineProperty来定义
    Object.defineProperty(person, name, {
      value: 'lyb'
    });
    
    console.log(person.name); // undefined
    console.log(person['name']); // undefined
    console.log(person[name]); // lyb
    
    let name = Symbol(),
        eat = Symbol('eat');
    
    let person = {
      [name]: name,
      [eat]() {
        console.log(this[name]);
      }
    };
    
    console.log(person); // {Symbol(): Symbol(), Symbol(eat): ƒ}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    5、Symbol的方法

    Symbol.for()

    Symbol()声明的值永远不相等,for方法就是用来声明相等的Symbol类型值

    ● Symbol.for(key)
    ● 通过for里的key值来声明相等的Symbol类型值

    let s = Symbol('foo');
    
    let s1 = Symbol.for('foo'),
        s2 = Symbol.for('foo');
    
    console.log(s === s1); // false
    console.log(s1 === s2); // true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Symbol.keyFor()

    获取Symbol.for()声明的key值

    ● Symbol.keyFor(key)
    ● 返回Symbol类型值的key

    let s = Symbol('foo');
    
    let s1 = Symbol.for('foo'),
        s2 = Symbol.for('foo');
    
    console.log(Symbol.keyFor(s1)); // foo
    console.log(Symbol.keyFor(s2)); // foo
    
    console.log(Symbol.keyFor(s1) === Symbol.keyFor(s1)); // true
    
    console.log(Symbol.keyFor(s)); // undefined
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    6、Symbol属性的遍历

    ● for in不可遍历Symbol属性的对象
    ● for of不可遍历Symbol属性的对象

    Object.getOwnPropertySymbols()

    ● 获取对象中的Symbol类型的属性
    ● 参数:目标对象
    ● 返回值:Symbol类型的属性组成的数组

    let s1 = Symbol('s1'),
        s2 = Symbol('s2');
    
    const obj = {};
    
    obj[s1] = 's1Symbol';
    obj[s2] = 's2Symbol';
    obj.s3 = 's3Str';
    
    console.log(obj); // {s3: 's3Str', Symbol(s1): 's1Symbol', Symbol(s2): 's2Symbol'}
    
    const objSym = Object.getOwnPropertySymbols(obj);
    console.log(objSym); // [Symbol(s1), Symbol(s2)]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    五、几种遍历的方式

    ● for in:遍历自身和可继承的可枚举的属性(不包含Symbol类型的)
    ● Object.keys():遍历自身的可枚举的属性(不包含Symbol类型的)
    ● Object.getOwnPropertySymbols():遍历自身的Symbol类型的值
    ● Object.assign():浅拷贝自身可枚举的包含Symbol类型的值
    ● JSON.stringify():遍历自身的可枚举的属性

  • 相关阅读:
    Linux下Samba服务安装及启用全攻略
    unity 实用框架
    SQL注入漏洞 | bool型
    css媒体查询新特性
    Frequently used Docker commands on Ubuntu
    Java访问Scala中的Int类型
    【SQL】索引失效的11种情况
    论文解读(NWR)《Graph Auto-Encoder via Neighborhood Wasserstein Reconstruction》
    计算机组成原理_Cache的基本概念
    解决Spring Cloud整合Nacos与Gateway的探险之旅
  • 原文地址:https://blog.csdn.net/Lyb__/article/details/125549803