javascript
javascript onsubmit返回false仍然能提交_JavaScript对象-Get和Put
这篇文章我们来了解一下对象属性值读写的具体过程。
1.getter和setter
之前我们了解了对象的属性描述符,这里我们来聊一下与之相对应的访问描述符-getter和setter。
在ES5中可以使用getter和setter部分改写默认操作,但是只能应用在单个属性上,无法应用在整个对象上。
getter是一个隐藏函数,会在获取属性值时调用。setter也是一个隐藏函数,会在设置属性值时调用。
当你给一个属性定义getter、setter或者两者都有时,这个属性会被定义为“访问描述符”(和“属性描述符”相对)。对于访问描述符来说,JavaScript会忽略它们的value和writable特性,取而代之的是关心set和get。
看一段代码:
var obj = {get a() {return 1;} }; Object.defineProperty(obj, 'b', {get: function(){return 2;} }); obj.a; //1 obj.b; //2上面代码展示的就是定义getter的两种方式,不管是对象文字语法中的get a(){..},还是defineProperty(..)中的显式定义,二者都会在对象中创建一个不包含值的属性,对于这个属性的访问会自动调用一个隐藏函数,它的返回值会被当作属性访问的返回值。
通常来说getter和setter是成对出现的,getter一般也不会只返回一个静态的值:
var obj = {get a() {return this._a_;},set a(val) {this._a_ = val * 2;} }; obj.a = 1; obj.a; //2对象中一个属性的getter/settter和writable/value不能同时被定义。
2.对象的读写
【下面的内容需要你对JavaScript的原型链有一定的了解】
1.[[Get]]
JavaScript中对象属性的访问是有一套完整的规则的,思考下面代码:
var obj = {a : 2}; obj.a; //2obj.a是一次属性的访问,但是这条语句并不仅仅是在obj中查找名字为a的属性。在JavaScript的语言规范中,obj.a实际上是实现了[[Get]]操作。
对象默认的内置[[Get]]操作首先在对象中查找是否有名称相同的属性,如果有,就返回这个属性的值。
如果没有,就会继续访问对象的原型([[Prototype]])链:
var obj1 = {a : 1}; var obj = Object.create(obj1); obj.hasOwnProperty('a'); //false obj.a; // 1Object.create会创建一个对象并把这个对象的[[Prototype]]关联到指定的对象。
可以通过Object.getPrototypeOf获取到对象的原型([[Prototype]]):
Object.getPrototypeOf(obj) === obj1; // true //在浏览器中,一般可以通过__proto__访问到对象原型 obj.__proto__ === obj1; // true现在obj的原型关联到了obj1。
在访问obj.a的时候,尽管a不存在于obj中,但是属性访问仍然成功的(在obj1中)找到了a的值为1。
如果obj中也找不到a并且原型链不为空的话,就会继续查找下去。
这个过程会持续到 找到匹配的属性名或者查找完整条原型链。如果是后者的话,[[Get]]操作的返回值是undefined。
所有普通的原型链最终都会指向内置的Object.prototype。
2.[[Put]]
既然有可以获取属性值的[[Get]]操作,就一定有对应的[[Put]]操作。 JavaScript中对象属性的设置是也有一套完整的规则的,思考下面代码:
var obj = {foo: 1}; obj.foo = 2; obj.foo; //2在给对象属性赋值的时候,如果已经存在这个属性,[[Put]]算法大致如下。
如果这个属性不存在,会出现以下3种情况:
1.如果在obj的原型链上层存在名为foo的普通数据访问属性并且没有被标记为只读(writable:false),那就会直接在obj中添加一个名为foo的新属性,它是屏蔽属性。
var obj1 = {foo : 1}; var obj = Object.create(obj1); obj.foo; //1 obj.foo = 2; obj.foo; //2 obj1.foo; //1什么是屏蔽属性?
如果一个属性名既出现在当前对象中也出现在当前对象的原型链上层,那么就会发生屏蔽。
当前对象中包含的属性会屏蔽原型链上层的所有同名属性,因为属性访问总是会选择原型链中最底层的属性。
上面代码片段中在给obj.foo重新赋值之后,再通过obj访问属性foo,就只能访问到新设置在当前foo对象上的foo的值了。
2.如果在obj的原型链上层存在foo,但是它被标记为只读(writable:false),那么无法修改已有属性或者在obj上创建屏蔽属性。如果运行在严格模式下,代码会抛出一个错误。
var obj1 = {} Object.defineProperty(obj1,'foo', {value: 1,writable: false }); var obj = Object.create(obj1); obj.foo; //1 obj.foo = 2;//严格模式会抛出错误TypeError obj.foo; //1 obj1.foo; //13.如果在obj的原型链上层存在foo并且它是一个setter,那就一定会调用这个setter。foo不会被添加到obj。
var obj1 = {}; Object.defineProperty(obj1, 'foo', {set: function(val){console.log('setter of obj1:' + val)} }) var obj = Object.create(obj1); obj.foo = 1; //输出:setter of obj1:1 obj.hasOwnProperty('foo'); //false从上面代码片段可以看出,在执行obj.foo的时候,实际上只执行了obj1.foo的setter方法,并没有在obj上创建屏蔽属性。
如果你希望在第二种和第三种情况下也屏蔽foo,那就不能使用=操作符来赋值,而是使用Object.defineProperty来向obj添加foo:
var obj1 = {} Object.defineProperty(obj1,'foo', {value: 1,writable: false }); var obj = Object.create(obj1); Object.defineProperty(obj,'foo', {value: 2 }); obj.foo; //2总结
以上是生活随笔为你收集整理的javascript onsubmit返回false仍然能提交_JavaScript对象-Get和Put的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 云端存储能代替U盘吗 谁会成为最后的王者
- 下一篇: pythin怎么根据月份获取月初和月末_