函数名.name:函数名获取

函数表达式方式,获取匿名函数名称

  1. var f=function (){
  2. console.log(arguments.callee.name); // f 可以拿到匿名函数
  3. console.log(f.name); // f
  4. }
  5. /*
  6. es5会打印空“” 因为现在都是es6,所以看不到es5的情况
  7. */
  8. console.log(f.name);//f
  9. f();

函数表达式方式,获取函数名称

名字被第二个覆盖了,但调用时得调用第一个名字

  1. var f = function fn() {
  2. console.log(arguments.callee.name); // fn
  3. console.log(f.name); // fn
  4. }
  5. console.log(f.name); // fn
  6. f();
  7. // fn();//ReferenceError: fn is not defined

new构造函数函数名字anonymous

  1. // console.log(new Function.name);//TypeError: Function.name is not a constructor
  2. console.log(new Function().name);//anonymous
  3. console.log((new Function).name);//anonymous

bind与函数名

  1. function foo(){}
  2. console.log(foo.name);//foo
  3. console.log(foo.bind({}).name);//bound foo
  4. //TypeError: Cannot read properties of undefined (reading 'name')

对象的扩展:对象简写

属性变量名一致时可以简写

  1. const foo="bar";
  2. const baz={foo};
  3. // const baz={foo:foo};
  4. console.log(baz);//{ foo: 'bar' }
  1. const foo="bar";
  2. const baz={foo};
  3. /*当属性名=变量名的时候可以简写
  4. * foo等价于
  5. * 属性名foo:变量名foo*/
  6. // const baz={foo:foo};
  7. console.log(baz);//{ foo: 'bar' }

image.png

  1. function foo(a,b){
  2. console.log({a,b});//{ a: 1, b: 2 }
  3. console.log({a:a*2,b:b*2});//{ a: 2, b: 4 }
  4. }
  5. foo(1,2);

方法简写

  1. const person={
  2. age:'12',
  3. say(){
  4. console.log(this.age)
  5. }
  6. }
  7. person.say()//12

箭头函数简写

  1. /*function foo(a,b){
  2. console.log({a,b});//{ a: 1, b: 2 }
  3. console.log({a:a*2,b:b*2});//{ a: 2, b: 4 }
  4. }
  5. foo(1,2);*/
  6. function foo(a=1,b=2){
  7. return {a,b}
  8. }
  9. let foo=(a=1,b=2)=>{a,b};

解构赋值应用:包的导出与引用

导出

root.js

  1. function foo() {
  2. console.log(1)
  3. }
  4. function bar() {
  5. console.log(2)
  6. }
  7. function baz() {
  8. console.log(3)
  9. }
  10. let a = 3;
  11. const obj = {
  12. a,
  13. foo,
  14. bar,
  15. baz
  16. }
  17. module.exports.obj=obj;
  18. console.log(obj);
  19. /*{
  20. a: 3,
  21. foo: [Function: foo],
  22. bar: [Function: bar],
  23. baz: [Function: baz]
  24. }*/

引用

main.js引用

  1. const obj=require('./root').obj;
  2. console.log(obj);
  3. /*{
  4. a: 3,
  5. foo: [Function: foo],
  6. bar: [Function: bar],
  7. baz: [Function: baz]
  8. }
  9. {
  10. a: 3,
  11. foo: [Function: foo],
  12. bar: [Function: bar],
  13. baz: [Function: baz]
  14. }
  15. */

通过解构赋值拿到对象

  1. // const obj=require('./root').obj;
  2. /*通过解构赋值从obj拿到属性*/
  3. // const {a:a,foo:foo,bar:bar,baz:baz}=require('./root').obj;
  4. const {a, foo, bar, baz} = require('./root').obj;
  5. console.log(a);//3
  6. foo();//1
  7. bar();//2
  8. baz();//3

属性是字符串

  1. var arr = [1, 23, 23, 45, 5];
  2. /*属性会进行包装,把所有传入的值进行一个包装,变成字符串
  3. * 定义的属性都是字符串*/
  4. console.log(arr[1]);//23
  5. console.log(arr["1"]);//23
  1. const obj={
  2. /* class(){
  3. }*/
  4. /*在对象中定义class方法,也可以,不冲突,但不推荐这样做
  5. * 其实是把class变成字符串*/
  6. "class":function (){
  7. }
  8. }

字符串可以用方法来利用它们

  1. let obj={};
  2. obj.foo=true;
  3. console.log(obj);//{ foo: true }
  4. /*拼接属性,通过表达式让属性拼接,变量相加减都是可以的*/
  5. obj['f'+'o'+'o']=false;
  6. console.log(obj);//{ foo: false }

通过字符串拼接成属性

属性名都会通过一种方式把它处理成字符串

  1. let a='hello';
  2. let b='world';
  3. /*三句话都是给obj的helloworld属性赋值*/
  4. let obj={
  5. [a+b]:true,
  6. ['hello'+b]:123,
  7. ['hello'+'world']:undefined
  8. }
  9. console.log(obj);//{ helloworld: undefined }

[true]、[obj]属性的转换

通过原型上的方法转换成字符串,再从对象中查找属性(字符串)
与类型有关,Number、Boolean、对象Object、数组也是对象但是用Array

  1. var myObject = {};
  2. /*直接把true变成字符串*/
  3. myObject[true] = 'foo';
  4. myObject[3] = 'bar';
  5. myObject[myObject] = 'baz';
  6. console.log(myObject);//{ '3': 'bar', true: 'foo', '[object Object]': 'baz' }
  7. console.log(myObject['true']);//foo
  8. console.log(myObject['3']);//bar
  9. console.log(myObject[myObject]);//baz
  10. /*myObject对象被Object.prototype.toString方法转换成/[object Object]字符串,注意有[],
  11. * 不是转换成myObject字符串*/
  12. console.log(myObject['myObject']);//undefined
  13. console.log(myObject['[object Object]']);//true
  14. console.log(Boolean.prototype.toString.call(true));//true
  15. console.log(Object.prototype.toString.call(myObject));//[object Object]

步骤类似于以下伪代码,对象[属性x],判断属性x的值进行不同的xxx.prototype.toString.call(x)转换

  1. /*伪代码不能运行*/
  2. var obj={};
  3. obj[x]=1;
  4. if(typeof x==='Number'){
  5. obj[Number.prototype.toString.call(x)]=1;
  6. }
  7. else if(typeof(x)==='Boolean' ){
  8. obj[Boolean.prototype.toString.call(x)]=1;
  9. }
  1. const a = {a: 1};
  2. const b = {b: 2};
  3. const obj={
  4. [a]:'valueA',
  5. [b]:'valueB'
  6. }
  7. console.log(obj);//{ '[object Object]': 'valueB' }

Array会用Array.prototype.toString转换

  1. var myObject = {};
  2. var arr = ['1', 2, 'san'];
  3. myObject[arr] = 'arr';
  4. console.log(myObject);//{ '1,2,san': 'arr' }
  5. console.log(Object.prototype.toString.call(arr));//[object Array]
  6. console.log(Array.prototype.toString.call(arr));//1,2,san

getOwnPropertyDescriptor检测属性特征的方法

es5之前js并没有提供一个直接检测属性特征的方法,比如检测一个属性是否是只读属性,是否可以遍历,这些属性在es5之前都没有

es5,属性描述符:可以理解成描述属性的键值对,属性:值,描述属性的对象
对象就是数据,方法也是数据,计算机一切都是数据,数据是,数据可以描述东西的

  1. let obj={a:2};
  2. console.log(Object.prototype);

image.png

getOwnPropertyDescriptor使用

Object.getOwnPropertyDescriptor(obj需要检测的对象 , ‘a‘对象中需要检测的属性) 查询obj中的a属性的特征

Object.getOwnPropertyDescriptor(obj,’a’)
参数一obj需要检测的对象
参数二’a’对象中需要检测的属性

return返回一个对象,对象里面有一系列数据,关于那个属性特征的数据,返回关于那个属性的描述符对象
用途:查询对象中的属性的描述符,特征

  1. let obj={a:2};
  2. // console.log(Object.prototype);
  3. console.log(Object.getOwnPropertyDescriptor(obj,'a'));

image.png
configurable:(可配置的),通过defineProperty添加一个新的属性,或者修改一个已有属性
enumerable:(可枚举)
writable:(可写)
value:(值)

defineProperty给对象定义属性

是给对象定义属性的,配置修改的是属性,不是对象
Object.defineProperty(obj查询的对象, ‘a‘查询的属性,{描述符})
用途:通过obj、a查到属性,再通过对象(描述符),修改对象属性的特征

  1. let obj = {};
  2. Object.defineProperty(obj, 'a',{
  3. value :2,
  4. enumerable : true,
  5. writable : true,
  6. configurable : true
  7. })
  8. console.log(obj);//{a:2}
  1. let obj = {};
  2. Object.defineProperty(obj, 'a', {
  3. value: 2,
  4. enumerable: true,
  5. writable: true,
  6. configurable: true
  7. })
  8. console.log(obj);//{a:2}
  9. console.log(Object.getOwnPropertyDescriptor(obj, 'a'));

image.png

writable:(可写)设置为false,设置的属性不可以更改值

  1. let obj = {};
  2. Object.defineProperty(obj, 'a', {
  3. value: 2,
  4. enumerable: true,
  5. /*设置为false,不可以更改*/
  6. writable: false,
  7. configurable: true
  8. })
  9. obj.a=3;
  10. /*es6在这里采取静默失败的策略,silenty field,属性没有生效,没有报错。
  11. * 偷偷不执行这条语句*/
  12. console.log(obj.a);//2

严格模式下报错

  1. "use strict";
  2. let obj = {};
  3. Object.defineProperty(obj, 'a', {
  4. value: 2,
  5. enumerable: true,
  6. /*设置为false,不可以更改*/
  7. writable: false,
  8. configurable: true
  9. })
  10. obj.a=3;
  11. //Uncaught TypeError: Cannot assign to read only property 'a' of object '#<Object>'
  12. /*es6在这里采取静默失败的策略,silenty field,属性没有生效,没有报错。
  13. * 偷偷不执行这条语句
  14. * 用严格模式use strict会报错*/
  15. console.log(obj.a);

但可以删除,虽然可以修改

  1. // "use strict";
  2. let obj = {};
  3. Object.defineProperty(obj, 'a', {
  4. value: 2,
  5. enumerable: true,
  6. /*设置为false,不可以更改,但可以删除,严格模式下删除也不报错*/
  7. writable: false,
  8. configurable: true
  9. })
  10. console.log(obj);//{a: 2}
  11. delete obj.a;
  12. console.log(obj.a);//undefined
  13. console.log(obj);//{}

configurable:(可配置的)设置为false,设置的属性不可删除

  1. // "use strict";
  2. let obj = {};
  3. Object.defineProperty(obj, 'a', {
  4. value: 2,
  5. enumerable: true,
  6. writable: true,
  7. /*configurable设置为false就不能删除了,configurable:false,不能删除;
  8. * 但可以修改,writable设置为true,可以修改,*/
  9. configurable: false
  10. })
  11. obj.a = 3;
  12. console.log(obj);//{a: 3}
  13. delete obj.a;
  14. console.log(obj.a);//3
  15. console.log(obj);//{a: 3}

getter,setter

1h19m
get操作,put操作

也是属性描述符,与writeable等一样,虽然打印只显示4个,但有没有显示的内容,比如getter等也是存在的
image.png

  1. let obj={a:1};
  2. obj.a;//[[Get]]操作
  3. /**
  4. * 当我们进行obj.a的时候,js引擎其实会通过[[Get]]来获取,
  5. *属性的获取,[[Get]]没有特定设置,执行默认操作:查找当前属性如果没有,查找原型,
  6. * */
  7. obj.a=3;
  8. /**
  9. * 赋值操作[Put],[Put]默认操作,
  10. * 1.getter;setter;
  11. * 2.writable:false,不让你改:
  12. * 3.赋值:
  13. *
  14. * time 1h27m35s
  15. * 1看操作是否是gettersetter 2是否可写 3赋值
  16. */

1h28m

getter setter

getter、setter改写获取属性的方式、设置属性的方式,

time 1h30m

get方式重写了当前的获取属性的默认方式

  1. var obj={
  2. log:['example','test'],
  3. get latest(){
  4. if (this.log.length===0) {
  5. return undefined;
  6. }
  7. return this.log[this.log.length-1];
  8. }
  9. }
  10. console.log(obj.latest);//test
  11. /*通过get方式重写了当前的获取属性的默认方式,obj.latest不再是之前原本的obj.a的方式来执行的,
  12. * 它访问值的方式是通过get的方式来定义的*/
  1. var obj={
  2. log:['example','test'],
  3. /**
  4. * get latest()不是一个方法,而是一个属性,一个值,所以需要return返回一个值,
  5. * 其实latest()本质上是一个方法,因为有get 所以必须有返回值,
  6. * obj.latest是得到obj里面latest里面的值,本来会走[[Get]]的默认操作的,但我
  7. * 通过get方式重写了获取属性的默认方式,现在获取latest属性值的方式是执行latest这个方法,
  8. * 并把方法的返回值作为latest的属性值,而不是找有没有叫latest的属性,并获取它的值
  9. * @returns {string|undefined}
  10. */
  11. get latest(){
  12. if (this.log.length===0) {
  13. return undefined;
  14. }
  15. return this.log[this.log.length-1];
  16. },
  17. latest1(){
  18. if (this.log.length===0) {
  19. return undefined;
  20. }
  21. return this.log[this.log.length-1];
  22. }
  23. }
  24. // console.log(obj.log)
  25. console.log(obj.latest);//test
  26. console.log(obj.latest1());//test
  27. /*通过get方式重写了当前的获取属性的默认方式,obj.latest不再是之前原本的obj.a的方式来执行的,
  28. * 它访问值的方式是通过get的方式来定义的*/
  1. var obj={
  2. log:['example','test'],
  3. get latest(){
  4. if (this.log.length===0) {
  5. return undefined;
  6. }
  7. return this.log[this.log.length-1];
  8. },
  9. latest1(){
  10. if (this.log.length===0) {
  11. return undefined;
  12. }
  13. return this.log[this.log.length-1];
  14. }
  15. }
  16. console.log(obj.latest);//test
  17. console.log(obj.latest1());//test
  18. /*通过get方式重写了当前的获取属性的默认方式,obj.latest不再是之前原本的obj.a的方式来执行的,
  19. * 它访问值的方式是通过get的方式来定义的*/

time 1h38m

  1. var myObject = {
  2. get a() {
  3. return 2;
  4. }
  5. }
  6. Object.defineProperty(myObject, 'b', {
  7. /*getenumerable等都是可描述属性,只不过赋值需要给它赋值方法function,*/
  8. get: function () {
  9. // return this.a (2);
  10. return this.a * 2;
  11. },
  12. enumerable: true,
  13. /* value:6,
  14. writable : true*/
  15. /*都会报错,因为get已经有值了,已经是赋值语句,就不能在下面再给值了
  16. * valuewriteable这俩是不让用的,与get方式矛盾,起冲突
  17. * configuableenumerable可以用*/
  18. })
  19. console.log(myObject.a);//2 执行a()方法,return2,作为a的返回值
  20. console.log(myObject.b);//4

time 1h46m
value与get冲突,不能都写
get、set可描述属性与value、writable属性不能同时存在

  1. var myObject = {
  2. get a() {
  3. return 2;
  4. }
  5. }
  6. Object.defineProperty(myObject, 'b', {
  7. get: function () {
  8. // return this.a (2);
  9. return this.a * 2;
  10. },
  11. enumerable: true,
  12. /* value:6,
  13. writable : true*/
  14. /*都会报错,因为get已经有值了,已经是赋值语句,就不能在下面再给值了
  15. * value、writeable这俩是不让用的,与get方式矛盾,起冲突
  16. * configuable、enumerable可以用*/
  17. })
  18. console.log(myObject.a);//2
  19. console.log(myObject.b);//4

image.png

time 1h51m
set设置,必须给它一个值才能set,所以必须加参数,所有set都必须要有参数

  1. var language = {
  2. set current() {
  3. },
  4. log: []
  5. }

image.png

time 1h53m

  1. var language = {
  2. set current(name) {
  3. this.log.push(name);
  4. },
  5. log: []
  6. }
  7. language.current = 'EN';
  8. console.log(language.log);//['EN']

分析

  1. var language = {
  2. set current(name) {
  3. this.log.push(name);
  4. },
  5. log: []
  6. }
  7. /**
  8. * 打印undefined,说明language.current = 'EN';不是给current这个属性赋值了,
  9. * 不是默认的set操作了,而是执行current方法,current('EN'),把=的EN作为参数传过去,
  10. * 执行方法,=号也不是默认的赋值操作了,而是传参,类似于传参,传了EN作为参数,
  11. * 传参需要先指定是哪个方法,language.current找到是哪个方法,找到哪个方法并传参并执行,
  12. * 执行了方法,所以log有值了
  13. */
  14. language.current = 'EN';
  15. console.log(language.current);//undefined
  16. console.log(language.log);//['EN']
  1. var language = {
  2. set current(name) {
  3. this.log.push(name);
  4. },
  5. log: []
  6. }
  7. language.current = 'EN';
  8. language.current = 'FA';
  9. console.log(language.log);//['EN', 'FA']
  10. console.log(language.current);//undefined
  11. console.log(language.current = 'TE');//TE
  12. console.log(language.current);//undefined
  13. console.log(language.log);//['EN', 'FA', 'TE']
  1. var language = {
  2. set current(name) {
  3. this.log.push(name);
  4. },
  5. current1(name) {
  6. this.log.push(name);
  7. },
  8. log: []
  9. }
  10. language.current = 'EN';
  11. language.current = 'FA';
  12. console.log(language.log);//['EN', 'FA']
  13. console.log(language.current);//undefined
  14. console.log(language.current = 'TE');//TE
  15. /* language.current = 'EN'不是之前的赋值语句了,而是执行set current函数=“FA”,
  16. * 就是current("FA")*/
  17. console.log(language.current);//undefined
  18. console.log(language.log);//['EN', 'FA', 'TE']

time 1h55m
obj.a=3;进行了赋值操作,我赋值再取值,obj.a还是走get a方法,返回2,值是不会改变的

  1. var obj={
  2. get a(){
  3. return 2;
  4. }
  5. }
  6. obj.a=3;
  7. console.log(obj.a);//2
  8. /*并不能等于3,一般有get属性,也得需要set属性,要不只能取值不能赋值,没有意义
  9. * 一般get、set都是成对出现的*/

time 1h56m27s
所以我需要get、set方法同时使用
get返回值不能写死,如果get就返回2,就永远取值时走get方法得到2
a属性的get方法、set方法

  1. var obj={
  2. get a(){
  3. return 2;
  4. },
  5. set a(val){
  6. // return this.a*2;//3
  7. return val*2;//3
  8. }
  9. }
  10. console.log(obj.a=3);//3
  11. console.log(obj.a);//2

time 2h

  1. var obj={
  2. get a(){
  3. // return 2;
  4. return this._a;
  5. },
  6. set a(val){
  7. // return this.a*2;//3
  8. // return val*2;//3
  9. this._a=val*2;
  10. }
  11. }
  12. console.log(obj.a=3);//3
  13. console.log(obj.a);//6

这个是get、set比较基本的用法,这个之后去练习

  1. var obj={
  2. get a(){
  3. // return 2;
  4. return this._a;
  5. },
  6. set a(val){
  7. // return this.a*2;//3
  8. // return val*2;//3
  9. this._a=val*2;
  10. }
  11. }
  12. /**
  13. * 赋值,走aset方法,this._a=3*2=6
  14. */
  15. console.log(obj.a=3);//3
  16. /**
  17. * 取值,走aget方法,return this._a,return 6,结果是6
  18. */
  19. console.log(obj.a);//6

time 2h2m
getter、setter操作,覆盖了原本的[[Get]]、[[Put]]操作