设置原型属性
通过proto设置,不好
function Person() {
this.name = 'zhangsan';
this.age = '18';
}
var person = new Person();
person.__proto__={a:1}
/*访问慢,性能不好,这样写影响所有在__proto__上面的所有原型对象,
* 虽然浏览器都支持这种写法,但他是内部属性,不可访问,并且有种种缺点*/
/*1语义化,内部属性;
* 2访问效率慢;
* 3所有继承自该原型的对象都会影响到;*/
console.log(person);
// console.log(Object.prototype);
setPrototypeOf设置原型
用这些方法修改原型
Object.setPrototypeOf();//(写的操作)
Object.getPrototypeOf();//(读取操作)
Object.create();//(生成操作)
修改obj,obj的原型变成proto对象
let proto = {
y: 20,
z: 40
}
let obj = {x: 10};
let obj1 = Object.setPrototypeOf(obj, proto);
console.log(obj===obj1);//true
原始值无法设置对象,没有设置成功
setPrototypeOf只要传的第一个值不是对象,不会有任何效果,绑定失效了,还是返回1
getPrototypeOf访问原型会变成包装类,new Number(1).prototype
let obj = Object.setPrototypeOf(1, {a: 1, b: 2});
console.log(obj);//1
console.log(Object.getPrototypeOf(obj));
console.log(Object.getPrototypeOf(1)===Number.prototype);//true
不会变成包装类,与下面代码不一样
let obj = Object.setPrototypeOf(new Number(1), {a: 1, b: 2});
console.log(obj);//1
console.log(Object.getPrototypeOf(obj));
let obj = Object.setPrototypeOf('foo', {a: 1, b: 2});
console.log(obj);//foo
console.log(Object.getPrototypeOf('foo')===String.prototype);//true
let obj = Object.setPrototypeOf(true, {a: 1, b: 2});
console.log(obj);//true
console.log(Object.getPrototypeOf(true)===Boolean.prototype);//true
null、undefined失败
let obj = Object.setPrototypeOf(undefined, {a: 1, b: 2});
console.log(obj);//Uncaught TypeError: Object.setPrototypeOf called on null or undefined
let obj = Object.setPrototypeOf(null, {a: 1, b: 2});
console.log(obj);//Uncaught TypeError: Object.setPrototypeOf called on null or undefined
keys、values、entries
enumerable : true时,才可以遍历
const foo = {
a: 1,
b: 2,
c: 3
}
Object.defineProperties(foo,{
d : {
value :4,
enumerable : true
},
f:{
value : 5,
enumerable:false
}
})
console.log(Object.keys(foo));//['a', 'b', 'c', 'd']
/*自身的可枚举的键名*/
console.log(Object.values(foo));//[1, 2, 3, 4]
/*自身的可以枚举的键名,对应的属性值*/
console.log(Object.entries(foo));
/*自身的可以枚举的键名,对应的键名:属性值*/
d=4并没有取到,没有被keys遍历到
const foo = {
a:1,
b:2,
c:3
}
Object.defineProperty(Object.prototype, 'd', {
value:4,
writable:true,
enumerable:true,
configurable:true
})
console.log(foo);//{a: 1, b: 2, c: 3}
var arr = Object.keys(foo);
console.log(arr);//['a', 'b', 'c']
三个方法都不能遍历原型上面的内容,属性
const foo = {
a:1,
b:2,
c:3
}
Object.defineProperty(Object.prototype, 'd', {
value:4,
writable:true,
enumerable:true,
configurable:true
})
/* console.log(foo);//{a: 1, b: 2, c: 3}
var arr = Object.keys(foo);
console.log(arr);//['a', 'b', 'c']*/
console.log(Object.keys(foo));//['a', 'b', 'c']
console.log(Object.values(foo));//[1, 2, 3]
console.log(Object.entries(foo));
包装类
var obj={};
var obj=1;
var obj=true;
// var obj={};
console.log(Object.keys({}));//[]
console.log(Object.keys(1));//[]
console.log(Object.keys(true));//[]
console.log(Object.keys('123'));//['0', '1', '2']
console.log(Object.values('123'));//['1', '2', '3']
console.log(Object.entries('123'));//[Array(2), Array(2), Array(2)]
super
super(指向的是对象的原型对象) —->this;
this有自己的原意,比如说它指向的是当前对象本身,
super也有自己的原意,父类,指向的是对象的原型对象
let proto = {
y: 20,
z: 40
}
let obj = {
x: 10
}
Object.setPrototypeOf(obj,proto);
console.log(obj);
let proto = {
y: 20,
z: 40
}
let obj = {
x: 10,
foo:super.y
}
Object.setPrototypeOf(obj,proto);
//Uncaught SyntaxError: 'super' keyword unexpected here
console.log(obj);
依然报错,foo箭头函数也会报错
函数、箭头函数都会报错
let proto = {
y: 20,
z: 40
}
let obj = {
x: 10,
// foo:super.y,
/* foo:function() {
console.log(super.y);
// Uncaught SyntaxError: 'super' keyword unexpected here
}*/
foo :()=>{
console.log(super.y);
// Uncaught SyntaxError: 'super' keyword unexpected here
}
}
Object.setPrototypeOf(obj,proto);
console.log(obj);
let proto = {
y: 20,
z: 40
}
let obj = {
x: 10,
foo() {
console.log(super.y);
//对象的简写的写法才能生效;
}
}
Object.setPrototypeOf(obj, proto);
obj.foo();//20
let proto = {
y: 20,
z: 40,
bar:function() {
console.log(this.y);
}
}
let obj = {
x: 10,
foo() {
// console.log(super.y);
//对象的简写的写法才能生效;
super.bar();
}
}
Object.setPrototypeOf(obj, proto);
obj.foo();//20
也没有问题,通过super调用方法
symbol
变量不重名可以通过let、const来定义,但对象里的属性不能通过let、const,可能会重名
symbol是一个原始值的类型
原始值类型的值
string number,boolean,null,undefined、symbol
引用值 Object、array、function
Symbol不是构造函数
Symbol不是构造函数Function,new 会报错,它是原始值,肯定不是构造函数function
console.log(new Symbol());//TypeError: Symbol is not a constructor
console.log(Symbol());//Symbol()
所有Symbol值都不一样
都不一样
let s1=Symbol();
let s2=Symbol();
console.log(s1===s2);//false
console.log(typeof s1);//symbol
console.log(typeof(s1));//symbol
不能挂载属性
挂不上属性
let s1=Symbol();
s1.a=1;
console.log(s1.a);//undefined
symbol是唯一的,那怎么找到它,通过传入参数,怎么区分不同的symbol的值,通过传参数
symbol本身值都是不一样的,传不传参数不影响,但想要找到,而不是赋予let xx=symbol,用xx,这时就需要参数了,参数就是数据,用参数区分,用数据查找
可以通过不同的参数,识别不同的symbol类型的值
let s1=Symbol('foo');
console.log(s1);//Symbol(foo)
s1.a=1;
console.log(s1.a);//undefined
会隐式转换成字符串
var obj = {a: 1};
let s1=Symbol(obj);
console.log(Object.prototype.toString.call(obj));//[object Object]
console.log(s1);//Symbol([object Object])
var obj = {a: 1};
// var s1=Symbol(null);///Symbol(null)
var s1=Symbol(undefined);//Symbol() 没有不是Symbol(undefined)
console.log(s1);
不能转换成数字
let s1=Symbol(null);
console.log(s1+1);//TypeError: Cannot convert a Symbol value to a number
let s1=Symbol(null);
console.log(Object.getPrototypeOf(s1));
// console.log(s1+1);//TypeError: Cannot convert a Symbol value to a number
// console.log(Number(s1))//TypeError: Cannot convert a Symbol value to a number
console.log(String(s1));//Symbol(null)
console.log(Boolean(s1));//true 只有Number不能转;
主要是以下三个方法
let s1=Symbol(null);
console.log(Object.getPrototypeOf(s1));
tostring方法
这个东西不太难,但知识点有点散,视频中是总结的,需要、应该对着视频把知识难点,知识点都给列下来,视频是保证听懂的,保证理解的,看视频理解知识点,把理解的知识点做成笔记,看视频听懂,必须做笔记,把知识点列下来,记录
let s1=Symbol(null);
console.log(s1.toString());//Symbol(null)
let s1=Symbol(null);
console.log(!s1);//false
console.log(s1+'');//TypeError: Cannot convert a Symbol value to a string
/*不能通过隐式转换,可以显示转换
* 唯一可以隐式转换的是取反!s1,不报错,其它都报错,隐式转换仅限于Boolean*/
console.log(s1.toString());//Symbol(null)
let name=Symbol();
let person={};
person.name='zhangsan';
/*.name自动转换成字符串,就不能用,想用name变量需要[]*/
console.log(person['name']);//zhangsan
let name=Symbol();
let person={};
person[name]='zhangsan';
console.log(person);//{ [Symbol()]: 'zhangsan' }
let name=Symbol();
let person={
[name]:'zhangsan'
};
console.log(person);//{ [Symbol()]: 'zhangsan' }
let name=Symbol();
let person={};
Object.defineProperty(person,name,{
value:'zhangsan'
})
console.log(person[name])//
console.log(person)//{}设置在原型上面了
[]与symbol
let name=Symbol();
let eat=Symbol();
let person={
[name]:'zhangsan',
[eat](){
console.log(this[name])
}
}
person[eat]();//zhangsan
for、keyfor
symbol与构造函数
console.log(Symbol);//ƒ Symbol() { [native code] }
console.log(Symbol());//Symbol()
/*Symbol比较奇怪,是构造函数,但是不能new,只能通过方法执行的方式来运行*/
这是顶层定义的,顶层是c++等,底层定义时就这样定义的
以后行不行不知道,现在不行
for
Symbo.for(key键名,标识符:类型字符串)
返回值与Symbol()一样返回Symbol类型的值
Symbol永远拿到的是不一样的字符串,独一无二symbol类型的值
let s1=Symbol('foo');
let s2=Symbol('foo');
console.log(s1===s2);//false
如果就想拿到一样的值,该怎么办?
/*s1的时候,找key值为foo的symbol存不存在,不存在,新建
* s2时时候,找key值为foo的symbol存不存在,存在,找之前声明过的symbol值*/
let s=Symbol('foo');
let s1=Symbol.for('foo');
let s2=Symbol.for('foo');
console.log(s1===s2);//true
keyfor
Symbo.keyfor(Symbol1,Symbol类型的值:类型Symbol)
作用:查找Symbol是的键值,并返回
返回值:Symbol的键值:字符串
let s=Symbol('foo');
let s1=Symbol.for('foo');
let s2=Symbol.for('foo');
console.log(s1===s2);//true
console.log(Symbol.keyFor(s1));//foo
console.log(Symbol.keyFor(s1)===Symbol.keyFor(s2));//true
console.log(Symbol.keyFor(s));//undefined
/*s并没有传key值,不是Symbol.for方法创造出来的*/
不能遍历Symbol属性的值
const obj={};
let a=Symbol('a');
let b=Symbol('b');
obj[a]='hello';
obj[b]='world';
obj.c='1';
for (let i in obj) {
/*只打印c的值,不会打印三个属性
* for in不能遍历 Symbol属性的对象;*/
console.log(i);//c
console.log(obj[i]);//1
console.log('run')//run
}
const obj={};
let a=Symbol('a');
let b=Symbol('b');
obj[a]='hello';
obj[b]='world';
obj.c='1';
for (let i in obj) {
/*只打印c的值,不会打印三个属性
* for in不能遍历 Symbol属性的对象;*/
console.log(i);//c
console.log(obj[i]);//1
console.log('run')//run
}
for (let i of obj) {//TypeError: obj is not iterable
console.log(i);
}
const obj={};
let a=Symbol('a');
let b=Symbol('b');
obj[a]='hello';
obj[b]='world';
obj.c='1';
for (let i in obj) {
/*只打印c的值,不会打印三个属性
* for in不能遍历 Symbol属性的对象;*/
console.log(i);//c
console.log(obj[i]);//1
console.log('run')//run
}
/*
for (let i of obj) {//TypeError: obj is not iterable
console.log(i);
}*/
var obj1={};
Object.assign(obj1,obj);
console.log(obj1);//{ c: '1', [Symbol(a)]: 'hello', [Symbol(b)]: 'world' }
/*可以被assign合并,但还是不能遍历合并的obj1,就想遍历怎么办?*/
getOwnPropertySymbols
var obj1={};
Object.assign(obj1,obj);
console.log(obj1);//{ c: '1', [Symbol(a)]: 'hello', [Symbol(b)]: 'world' }
/*可以被assign合并,但还是不能遍历合并的obj1,就想遍历怎么办?*/
const objectSymbols=Object.getOwnPropertySymbols(obj);
/*只会遍历obj中Symbol属性的值*/
console.log(objectSymbols);//[ Symbol(a), 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);
console.log('--------')
for (let i in obj) {
console.log(i);
}
console.log('--------')
console.log(Object.keys(obj));
console.log('--------')
console.log(Object.getOwnPropertySymbols(obj));
解析
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);
console.log('--------')
/*for in遍历自身和继承的可枚举属性(不包含Symbol类型的值);*/
for (let i in obj) {
console.log(i);
}
console.log('--------')
console.log(Object.keys(obj));
/*遍历自身可枚举的属性,不包含Symbol类型的值,需要可以枚举
* 不包含继承*/
console.log('--------')
console.log(Object.getOwnPropertySymbols(obj));
/*遍历自身Symbol上面的值,不需要可枚举,不可枚举的,也可以遍历*/
var obj3 = {};
Object.assign(obj3, obj);
/*遍历自身可枚举的,包含symbol类型值的*/
console.log(obj3)
JSON.stringify()
/*遍历自身可枚举的,不包含symbol*/