摘要:所以对象也可说是一组名字属性的组合。如果想要访问,就用专用的方法,包含两个参数对象名称,属性名称,返回一个对象包含具体的特性。
基于《javascript 面向对象精要》整理下思路:
ECMA5 对象的定义是无序属性的集合,属性可以是基本值,对象(包含函数),属性都有一个名字,名字可以是标识符或者是字符串,映射到属性。所以对象也可说是一组名字/属性的组合。
有两种方式创建对象:构造函数,字面量;
//构造函数,先定义,在赋值 var obj1 = new Object(); obj1.name = "obama"; //字面量,直接赋值 var obj2 = { name : "bush" }
读取属性也有两种方式
obj1.name //常用的是使用 . 点号直接读取属性 obj1["name"] //使用中括号里面是属性的字符串(有引号)也可以读取 //如果属性包含空格或者其他的非合法标识符就只能使用中括号,
属性有两种:
1,数据属性 named data property
2,访问器属性 named accessor property
两者的区别,先看数据属性的例子
var obj = { name : "obama" } obj.name; consle.log(obj.name) //obama //正常情况下,直接访问obj.name 不会输出任何结果,只是引擎访问这个属性,等待下一步的操 //作,如果有下一步操作,就把这属性的值返回出来,提供使用如:console.log()。
也就是说,数据属性包含属性的具体的值,我们可以访问,访问器属性则没有,只供引擎使用,
那么如何描述这两个属性呢,那就是特性,attribute(描述对象属性的属性),正常情况下,不可访问,在内部用[[ ]]包裹。如果想要访问,就用专用的方法,
Object.getOwnPropertyDescriptor(object,property)包含两个参数(对象名称,属性名称),返回一个对象包含具体的特性。
var obj = { name : "obama" } var properties = Object.getOwnPropertyDescriptor(obj,"name"); console.dir(properties);
可以看到有四个属性,这些就是属性的数据属性,我们可以访问的到的,也是可以修改的,使用两个特殊的方法
Object.defineProperty(); 定义单个对象的属性
Object.defineProperties(); 定义多个对象的属性
记住使用以上两个函数,会对把有真假值特性默认为false,而正常JS里都是true,如果定义的属性不存在就会创建新的属性!!
var obj1 = { }; Object.defineProperty(obj1,"name",{ configurable : true, //决定其他特性是否可以修改,包含直接删除delete属性值即value; enumerable : true, //是否可以枚举 writable : true, //value 是否可以修改 value : "obama" //对象属性真正保存值的地方,上面的都是对它的描述 } ); var obj1 = { name : "obama" }
上面的两个对象是相等的,我们在直接些对象字面量的同时,JS引擎就默认生成了上面的属性,我们也可以修改下
var obj1 = { }; Object.defineProperty(obj1,"name",{ configurable : true, enumerable : false, writable : true, value : "obama" } ); //下面的函数需要是枚举特性才能使用 obj1.propertyIsEnumerable("name"); //false console.dir( Object.keys(obj1)); //数组是空 var properties; for(properties in obj1){ console.log("it has been search") // undefined } //*以下是误区,in和hasOwnProperty函数查找的是否有属性,不论是否可以枚举* console.log("name" in obj1); //true console.log(obj1.hasOwnProperty("name")) //true
当然我们也可以同时定义多个属性
var obj = { }; Object.defineProperties(obj,{ name:{ configurable : true, enumerable : true, writable : true, value : "obama" }, age :{ configurable : true, enumerable : true, writable : true, value : 77 }, behavior: { configurable : true, enumerable : true, writable : true, value : function(){ alert("i am the presdent of Amerca") } } }); obj = { name : "obama", age : 77, behavior : function(){ alert("i am the presdent of Amerca")} }
下面说说访问器属性,目前没有方法,直接查看所有的特性,但是我们可以设置特性,和数据属性使用一样的方法,没有value 和writable这两个属性,但是多[[get]]和[[set]]的方法;
//字面量 var obj = { _name : "obama", //使用下划线_ 只是约定成俗的写法,表示私有的(实际上我们也能访问) get name(){ //get 后面的name就是我们可以访问正常的属性, return this._name; }, set name(value){ this._name = value; } }; //或者使用函数 var obj = { _name : "obama" }; Object.defineProperty(obj,"name",{ get : function (){ return this._name; }, set : function(value){ this._name = value; }, configurable : true, enumerable : true }) console.log(obj.name) //obama
访问器属性有趣的地方在于如果我们把get的方法换成其他,比如不返回它的值
get : function(){ return console.log(’i am Kim Jong-un‘); } obj.name //即使只是写出这个属性也会输出’i am Kim Jong-un’
我们通过obj.name永远得不到想要的值,当然这样设置没有任何意思,只是了解JS是如何取得属性的值,
同时设置数据属性和访问器属性是会得到一个错误。
属性首次添加给对象时,JS就会在对象上调用[[Put]]方法,在对象内部开辟新的节点保存属性,这个新属性有默认的特性,重点是这个属性仅会保存在这对象上,也就是说是这个对象的自有属性!自有!自有![[Extensible]]方法,确定对象是否可以扩展,有三个具体的方法:
1,禁止扩展
var obj = { name : "obama" }; Object.preventExtensions(obj); obj.age = 77; console.log(obj.age) //undefined; //无法增加属性,但是可以修改删除原有属性 Object.isExtensible(obj) //false 表示不可以扩展!
2,对象封印
var obj = { name : "obama" }; Object.seal(obj); //不仅不可以扩展也不可删除属性,只能读写 delete obj.name //false obj.name = " Kim Jong-un"; console.log(obj.name) // Kim Jong-un //可以修改属性的writable(修改后只能读取),只能true ->false,不能false ->true; Object.isSealed(obj); //true; Object.isExtensible(obj) //false;
3,对象冻结
var obj = { name : "obama" }; Object.freeze(obj); //冻结后只可以读取值,,不可以修改删除值 Object.isFrozen(obj) //true; Object.isSealed(obj); //true; Object.isExtensible(obj) //false;
对象还有一个实用的方法,Object.getOwnPropertyNames();在对象本身的属性不可以枚举的情况下也能列出,返回一个数组,对比Object.keys() 只能列举可以枚举的.
注:上面的例子在严格模式下会抛出错误,非严格模式会失败
使用构造函数创建对象存在一个问题,就是必须使用new 操作符,构造函数也是函数如果直接调用的话,会把内部的this作用域指向全局;
function Fn(args){ this.args = args; } var obj1 = Fn("test"); obj1 //undefined args //test var obj2 = new Fn("test"); obj2.args //test; //安全的构造函数 function Fn(args){ if( this instanceof Fn){ this.args = args; }else{ return new Fn(args) } } //也可以使用Object.creat()的方法来创建对象 var obj1 = { }; var obj2 = Object.create(null); //obj2是一个真正意义上空的对象,没有任何的继承,比obj1更空,obj1继承Object对象的属性和方法。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/85164.html
摘要:所以觉得把这个执行的详细过程整理一下,帮助更好的理解。类似的语法报错的如下图所示三预编译阶段代码块通过语法分析阶段之后,语法都正确的下回进入预编译阶段。另开出新文章详细分析,主要介绍执行阶段中的同步任务执行和异步任务执行机制事件循环。 一、概述 js是一种非常灵活的语言,理解js引擎的执行过程对于我们学习js是非常有必要的。看了很多这方便文章,大多数是讲的是事件循环(event loo...
摘要:所以觉得把这个执行的详细过程整理一下,帮助更好的理解。类似的语法报错的如下图所示三预编译阶段代码块通过语法分析阶段之后,语法都正确的下回进入预编译阶段。另开出新文章详细分析,主要介绍执行阶段中的同步任务执行和异步任务执行机制事件循环。 一、概述 js是一种非常灵活的语言,理解js引擎的执行过程对于我们学习js是非常有必要的。看了很多这方便文章,大多数是讲的是事件循环(event loo...
摘要:以下知识点是前辈师兄总结基础语义化标签引进了一些新的标签,特别注意等,注意的标题结构理解浏览器解析的过程,理解的树形结构,及相应理解标签在各个浏览器上的默认样式代理样式,理解中的重置样式表的概念理解等功能性标签理解标签,理解文件提交过程推荐 以下知识点是前辈师兄总结 1、HTML/HTML5基础: 1.0、语义化H5标签1.1、H5引进了一些新的标签,特别注意article...
摘要:以下知识点是前辈师兄总结基础语义化标签引进了一些新的标签,特别注意等,注意的标题结构理解浏览器解析的过程,理解的树形结构,及相应理解标签在各个浏览器上的默认样式代理样式,理解中的重置样式表的概念理解等功能性标签理解标签,理解文件提交过程推荐 以下知识点是前辈师兄总结 1、HTML/HTML5基础: 1.0、语义化H5标签1.1、H5引进了一些新的标签,特别注意article...
摘要:至此作用域链创建完毕。好了,通过深入理解作用域链,我们能跟好的理解的运行机制和闭包的原理。 前言 理解javascript中的作用域和作用域链对我们理解js这们语言。这次想深入的聊下关于js执行的内部机制,主要讨论下,作用域,作用域链,闭包的概念。为了更好的理解这些东西,我模拟了当一个函数执行时,js引擎做了哪些事情--那些我们看不见的动作。 关键词: 执行环境 作用域 作用域链 变...
20190124问: 如何理解es6中的Proxy? 试题解析:对proxy的理解,可能会延伸到vue的双向绑定 Proxy(代理) 定义 可以理解为为目标对象架设一层拦截,外界对该对象的访问,都必须通过这层拦截 简单示例: const obj = new Proxy({}, { get: (target, key, receiver) => { return JS ...
阅读 1658·2021-11-24 09:39
阅读 2405·2021-11-18 10:07
阅读 3611·2021-08-31 09:40
阅读 3171·2019-08-30 15:44
阅读 2534·2019-08-30 12:50
阅读 3582·2019-08-26 17:04
阅读 1391·2019-08-26 13:49
阅读 1204·2019-08-23 18:05