ES6-10【super、4种遍历方式、原型、symbol遍历】

一.原型

(1).原型知识拓展

1.我们需要牢记两点

(1).__proto__ 和constructor属性是对象所独有的;

(2).prototype属性是函数所独有的;因为函数也是一种对象,所以也拥有__proto__和constructor属性

2.__proto__属性的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,,那么就会去它的__proto__属性所指向的那个对象(父对象)里找,直到找到__proto__属性的终点null,再往上找就相当于在null上取值,会报错。通过__proto__属性将对象连接起来的这条链路即我们所谓的原型链

3.prototype属性的作用就是让该函数所实例化的对象们都可以找到公有的属性和方法,即f1.__proto__ === Foo.prototype

4.constructor属性的含义就是指向该对象的构造函数,所有函数最终的构造函数都指向Function

(2).原型改变

.__protorype__这种方式非常影响性能,建议采用下方get set

常规做法
var person = new Person();
person.__proto__ = {}
//语义化不好,且是内部属性
//访问效率慢
//所有继承子该原型的对象都会影响到

新做法
Object.setPrototypeOf(person,{});

(3).Object.setPrototypeOf/Object.getPrototypeOf

Object.setPrototypeOf()写的操作

Object.getPrototypeOf()读取操作

第一个参数就是指定原型,第二个是指定要改变的对象

let proto = {
    y: 20,
    z: 40
}
let obj = {x: 10};
let obj1 = Object.setPrototypeOf(obj,proto);
log(obj1 === obj) // true;所以直接调用就可以了
log(obj)
//{x:10
    __proto__:
        y:20 
        z:40
 }  

(4).第一个参数为值类型

会自动转换第一个参数为对象,但是要根据情况判断能否把第二个参数放在第一个的原型上

let obj = Object.setPrototypeOf(1,{});
log(obj); //1

let obj = Object.setPrototypeOf(1,{a:1,b:2});
log(obj);//Number{0,...一系列方法}
原因是第一次传的是空对象没有生效,第二个生效了,但是是通过包装类包装后,默认值则为0,
证明这样的方式是无效的

log(Object.getPrototypeOf(1) === Number.prototype)//true

所以系统无法将第二个参数放到指定原型,直接通过包装类指定了,所以第二个参数指定失败了

所以如果第一个参数不是对象,那么就代表者指定不会有任何效果,原型会是原本的构造函数的原型

第一个值为字符串类型boolean类型都与上方结果一致,不做演示

un null报错

二.四种遍历方式

(1).keys/values

const foo = {
    a: 1,
    b: 2,
    c: 3
}
Object.defineProperties(foo,{
    d:{
        value: 4,
        enumerable: true
    },
    f:{
        value: 5,
        enumerable: false
    }
})
log(Object.keys(foo));
//['a','b','c','d']

不可枚举的无法获取,继承属性无法获取valus 同理,获取的为值

(3).entries

log(Object.entries(foo));
["a",1]["b",2]["c",3]["d",4]

不可枚举的无法获取,继承属性无法获取

获取的为键名键值

(4).字符串

let obj = '123'
log(Object.keys(obj));
//[0,1,2] 
//1和true 都是[]
//un和null会报错

都是一脉相承的所以values和entries一致

三.super

super指向的是对象的原型对象和this作用有点像

错误示范

let proto = {
    y: 20,
    z: 40
}
let obj = {
    x : 10,
    foo: super.y // 报错
    foo:()=>{
        log(super.y) // 报错
    }
}
Object.setPrototypeOf(obj,proto);
obj.foo();

正确写法

在对象的方法中才能生效,而且必需为简写的情况下

let proto = {
    y: 20,
    z: 40,
    bar(){
        this.y
    }
}
let obj = {
    x: 10,
    foo(){
        log(super.y);
    },
     doo(){
       super.bar();
    }
}
Object.setPrototypeOf(obj,proto);
obj.foo();//20
原型的方法也能访问
obJ.doo();//20

四.symbol

解决对象的属性名重名而生

(1).原始值类型

String Number Boolean null un symbol

(2).各类特征

它不是构造函数!所以不能实例化

是独一无二的值

let s1 = Symbol();
let s2 = Symbol();
log(s1 === s2);//false

单独的类型

let s1 = Symbol();
let s2 = Symbol();
log(typeof s1);//symbol

挂不上属性

let sq = Symbol();
sq.a = 1;//挂不上属性
log(sq.a)//输出Un

识别通过标识符识别

这样写是没有用的依旧不是标识符

let s1 = Symbol('foo')

类型转换

自动将传入参数转化为字符串

var obj = {a: 1};
let s1 = Symbol(obj);
log(s1); //Symbol([object Object])

如果传入null则是symbol(null)

un则是 symbol()

传入Number类型不能转化输出symbol()

传入String类型可以转化

传入Boolean类型可以转化

原型

原型是Symbol

let s1 = Symbol(null);
log(Object.getPrototypeOf(s1));

原型如图

tosString方法

let s1 = Symbol(null);
log(s1.toString());//symbol(null)

隐式转换

let s1 = Symbol(null);
log(s1+'');//报错
log(!s1);//false
log(s1+1)报错

只有boolean才能隐式转换

写入对象

let name = Symbol();
let person = {};
person[name] = 'zhangsan';
log(person);//{Symbol():"zhangsan"}
通过symbol来声明  .name就是字符串访问了所以不行

let name = Symbol();
let person = {
    [name]: 'zhangsan'
};
log(person);//{Symbol():"zhangsan"}

defineProperty
Object.defineProperty(person, name, {
    value: 'zhangsan'
})
log(person);//{Symbol():"zhangsan"}
log(person.name);//un

正确使用方式
let name = Symbol();
let eat = Symbol();
let person = {
    [name]: 'zhangsan',
    [eat](){
        log(this[name])
    }
}
person[name]();

(2).Symbol.for()/Symbol.keyFor()

for

设置标识符

问题在上面已经出现过了,就是括号内填入值也无法鉴别

let s1 = Symbol('foo');
let s2 = Symbol('foo');
log(s1 === s2);//就算标识符一致也打印false

let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');
log(s1 === s2);//true

let s1 = Symbol('foo');
let s2 = Symbol.for('foo');
log(s1 === s2);//false

keyfor

拿到标识符

let s1 = Symbol('foo');
let s2 = Symbol.for('foo');
log(Symbol.keyFor(s1));//un
log(Symbol.keyFor(s2));//foo

所以证明直接设置没登记在for中

(3).遍历

forin /assign

forin 遍历不到symbol的属性的对象

const obj = {}
let a = Symbol('a');
let b = Symbol('b');
obj[a] = 'hello';
obj[b] = 'world';
obj.c = 'hh'
log(obj)
for(let i in obj){
    log(i)
}//{c:haha}

var obj1 = {}
Object.assign(obj1 ,obj);
log(obj1 );
{
    c:'hh'
    Symbol(a): 'hello'
    Symbol(b): 'word'
}
我虽然能显示,但是我怎么才能调用呢?
如下

getOwnPropertySymbols(obj)

专门遍历Symbols用的

const objectSymbols = Object.getOwnPropertySymbols(obj);
log(objectSymbols);
//[
    0:Symbol(a)
    1:Symbol(b)
]

综合示例

const obj = {c:1, d:2};
let a = Symbol('a');
let b = Symbol('b');
let _a = Symbol('_a');
let _b = Symbol('_b');
obj[a] = 'hello';
obj[b] = 'world';
Object.defineProperties(obj,{
    e:{
        value: 5,
        enumerable: true
    },
    f:{
        value: 6,
        enumerable: false
    },
    [_a]:{
        value: -1,
        enumerable: true
    },
    [_b]:{
        value: -2,
        enumerable: false
    },
})
let h = Symbol('h');
let i = Symbol('i');
let j = Symbol('j');
const obj1 = {
    g: 7,
    [h]: 8
}
Object.defineProperties(obj1,{
    [i]:{
        value: 9,
        enumerable: true
    },
    [j]:{
        value: 10
    },
    k:{
        value: 11
    }
})
Object.setPrototypeOf(obj, obj1)
console.log(obj)
{
c: 1
d: 2
e: 5
f: 6
Symbol(a): "hello"
Symbol(b): "world"
Symbol(_a): -1
Symbol(_b): -2//灰色
__proto__:
g: 7
k: 11 //灰色
Symbol(h): 8
Symbol(i): 9
Symbol(j): 10//灰色
__proto__: Object




}
可枚举不可枚举 原型上的 是symbol的

for(let i in obj){
    console.log(i)
}
c d e g
可枚举的 不是Symbol的 原型上的也出来

console.log(Object.keys(obj))
[
0: "c"
1: "d"
2: "e"
]
可枚举的 不是symbol的 不是原型的


console.log(Object.getOwnPropertySymbols(obj))
[
0: Symbol(a)
1: Symbol(b)
2: Symbol(_a)
3: Symbol(_b)
length: 4
]
不是原型的 不管你枚举不枚举

var obj3 = {}
Object.assign(obj3,obj);
console.log(obj3)
{
c: 1
d: 2
e: 5
Symbol(a): "hello"
Symbol(b): "world"
Symbol(_a): -1
}
自身的,可枚举的 包含Symbol

Json.stringify()//遍历自身可枚举的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值