函数名
var f=function (){console.log(arguments.callee.name); // f 可以拿到匿名函数console.log(f.name); // f}/*es5会打印空“” 因为现在都是es6,所以看不到es5的情况*/console.log(f.name);//ff();
// console.log(new Function.name);//TypeError: Function.name is not a constructorconsole.log(new Function().name);//anonymousconsole.log((new Function).name);//anonymous
function foo(){}console.log(foo.name);//fooconsole.log(foo.bind({}).name);//bound fooconsole.log(foo.call({}).name);//TypeError: Cannot read properties of undefined (reading 'name')
对象的扩展
const foo="bar";const baz={foo};// const baz={foo:foo};console.log(baz);//{ foo: 'bar' }
const foo="bar";const baz={foo};/*当属性名=变量名的时候可以简写* foo等价于* 属性名foo:变量名foo*/// const baz={foo:foo};console.log(baz);//{ foo: 'bar' }

function foo(a,b){console.log({a,b});//{ a: 1, b: 2 }console.log({a:a*2,b:b*2});//{ a: 2, b: 4 }}foo(1,2);
const person={age:'12',say(){console.log(this.age)}}person.say()//12
/*function foo(a,b){console.log({a,b});//{ a: 1, b: 2 }console.log({a:a*2,b:b*2});//{ a: 2, b: 4 }}foo(1,2);*/function foo(a=1,b=2){return {a,b}}let foo=(a=1,b=2)=>{a,b};
root.js
function foo() {console.log(1)}function bar() {console.log(2)}function baz() {console.log(3)}let a = 3;const obj = {a,foo,bar,baz}module.exports.obj=obj;console.log(obj);/*{a: 3,foo: [Function: foo],bar: [Function: bar],baz: [Function: baz]}*/
main.js引用
const obj=require('./root').obj;console.log(obj);/*{a: 3,foo: [Function: foo],bar: [Function: bar],baz: [Function: baz]}{a: 3,foo: [Function: foo],bar: [Function: bar],baz: [Function: baz]}*/
// const obj=require('./root').obj;/*通过解构赋值从obj拿到属性*/// const {a:a,foo:foo,bar:bar,baz:baz}=require('./root').obj;const {a, foo, bar, baz} = require('./root').obj;console.log(a);//3foo();//1bar();//2baz();//3
var arr = [1, 23, 23, 45, 5];/*属性会进行包装,把所有传入的值进行一个包装,变成字符串* 定义的属性都是字符串*/console.log(arr[1]);//23console.log(arr["1"]);//23
const obj={/* class(){}*//*在对象中定义class方法,也可以,不冲突,但不推荐这样做* 其实是把class变成字符串*/"class":function (){}}
字符串可以用方法来利用它们
let obj={};obj.foo=true;console.log(obj);//{ foo: true }/*拼接属性,通过表达式让属性拼接,变量相加减都是可以的*/obj['f'+'o'+'o']=false;console.log(obj);//{ foo: false }
属性名都会通过一种方式把它处理成字符串
let a='hello';let b='world';/*三句话都是给obj的helloworld属性赋值*/let obj={[a+b]:true,['hello'+b]:123,['hello'+'world']:undefined}console.log(obj);//{ helloworld: undefined }
var myObject = {};/*直接把true变成字符串*/myObject[true] = 'foo';myObject[3] = 'bar';myObject[myObject] = 'baz';console.log(myObject);//{ '3': 'bar', true: 'foo', '[object Object]': 'baz' }console.log(myObject['true']);//fooconsole.log(myObject['3']);//barconsole.log(myObject[myObject]);//baz/*myObject对象被Object.prototype.toString方法转换成/[object Object]字符串,注意有[],* 不是转换成myObject字符串*/console.log(myObject['myObject']);//undefinedconsole.log(myObject['[object Object]']);//trueconsole.log(Boolean.prototype.toString.call(true));//trueconsole.log(Object.prototype.toString.call(myObject));//[object Object]
const a = {a: 1};const b = {b: 2};const obj={[a]:'valueA',[b]:'valueB'}console.log(obj);//{ '[object Object]': 'valueB' }
es5之前js并没有提供一个直接检测属性特征的方法,比如检测一个属性是否是只读属性,是否可以遍历,这些属性在es5之前都没有
es5,属性描述符:
let obj={a:2};console.log(Object.prototype);

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

configurable:(可配置的),通过defineProperty添加一个新的属性,或者修改一个已有属性
enumerable:(可枚举)
writable:(可写)
value:(值)
let obj = {};Object.defineProperty(obj, 'a',{value :2,enumerable : true,writable : true,configurable : true})console.log(obj);//{a:2}
let obj = {};Object.defineProperty(obj, 'a', {value: 2,enumerable: true,writable: true,configurable: true})console.log(obj);//{a:2}console.log(Object.getOwnPropertyDescriptor(obj, 'a'));

let obj = {};Object.defineProperty(obj, 'a', {value: 2,enumerable: true,/*设置为false,不可以更改*/writable: false,configurable: true})obj.a=3;/*es6在这里采取静默失败的策略,silenty field,属性没有生效,没有报错。* 偷偷不执行这条语句*/console.log(obj.a);//2
"use strict";let obj = {};Object.defineProperty(obj, 'a', {value: 2,enumerable: true,/*设置为false,不可以更改*/writable: false,configurable: true})obj.a=3;//Uncaught TypeError: Cannot assign to read only property 'a' of object '#<Object>'/*es6在这里采取静默失败的策略,silenty field,属性没有生效,没有报错。* 偷偷不执行这条语句* 用严格模式use strict会报错*/console.log(obj.a);
// "use strict";let obj = {};Object.defineProperty(obj, 'a', {value: 2,enumerable: true,/*设置为false,不可以更改,但可以删除,严格模式下删除也不报错*/writable: false,configurable: true})console.log(obj);//{a: 2}delete obj.a;console.log(obj.a);//undefinedconsole.log(obj);//{}
// "use strict";let obj = {};Object.defineProperty(obj, 'a', {value: 2,enumerable: true,writable: true,/*configurable设置为false就不能删除了,configurable:false,不能删除;* 但可以修改,writable设置为true,可以修改,*/configurable: false})obj.a = 3;console.log(obj);//{a: 3}delete obj.a;console.log(obj.a);//3console.log(obj);//{a: 3}
getter,setter
get操作,put操作
var obj={log:['example','test'],get latest(){if (this.log.length===0) {return undefined;}return this.log[this.log.length-1];}}console.log(obj.latest);//test/*通过get方式重写了当前的获取属性的默认方式,obj.latest不再是之前原本的obj.a的方式来执行的,* 它访问值的方式是通过get的方式来定义的*/
var obj={log:['example','test'],get latest(){if (this.log.length===0) {return undefined;}return this.log[this.log.length-1];},latest1(){if (this.log.length===0) {return undefined;}return this.log[this.log.length-1];}}console.log(obj.latest);//testconsole.log(obj.latest1());//test/*通过get方式重写了当前的获取属性的默认方式,obj.latest不再是之前原本的obj.a的方式来执行的,* 它访问值的方式是通过get的方式来定义的*/
var myObject = {get a() {return 2;}}Object.defineProperty(myObject, 'b', {get: function () {// return this.a (2);return this.a * 2;},enumerable: true,/* value:6,writable : true*//*都会报错,因为get已经有值了,已经是赋值语句,就不能在下面再给值了* value、writeable这俩是不让用的,与get方式矛盾,起冲突* configuable、enumerable可以用*/})console.log(myObject.a);//2console.log(myObject.b);//4

var language = {set current(name) {this.log.push(name);},log: []}language.current = 'EN';language.current = 'FA';console.log(language.log);//['EN', 'FA']console.log(language.current);//undefinedconsole.log(language.current = 'TE');//TEconsole.log(language.current);//undefinedconsole.log(language.log);//['EN', 'FA', 'TE']
var language = {set current(name) {this.log.push(name);},current1(name) {this.log.push(name);},log: []}language.current = 'EN';language.current = 'FA';console.log(language.log);//['EN', 'FA']console.log(language.current);//undefinedconsole.log(language.current = 'TE');//TE/* language.current = 'EN'不是之前的赋值语句了,而是执行set current函数=“FA”,* 就是current("FA")*/console.log(language.current);//undefinedconsole.log(language.log);//['EN', 'FA', 'TE']
var obj={get a(){return 2;}}obj.a=3;console.log(obj.a);//2/*并不能等于3,一般有get属性,也得需要set属性,要不只能取值不能赋值,没有意义* 一般get、set都是成对出现的*/
var obj={get a(){return 2;},set a(val){// return this.a*2;//3return val*2;//3}}console.log(obj.a=3);//3console.log(obj.a);//2
var obj={get a(){// return 2;return this._a;},set a(val){// return this.a*2;//3// return val*2;//3this._a=val*2;}}console.log(obj.a=3);//3console.log(obj.a);//6
这个是get、set比较基本的用法,这个之后去练习
getter、setter操作,覆盖了原本的[[Get]]、[[Put]]操作
