Last active
September 18, 2015 04:53
-
-
Save kenyonduan/4667de99d945764dfc1d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var duan = { | |
name: 'duan', | |
email: 'duan@easya.cc' | |
}; | |
//查看对象所有的的属性名称 | |
Object.getOwnPropertyNames //=> ["name", "email"] | |
//查看对象属性的配置 | |
Object.getOwnPropertyDescriptor(duan, 'name') //=> Object {value: "duan", writable: true, enumerable: true, configurable: true} 这个是什么? | |
//属性的配置(可以用来动态的为对象添加属性(值、方法) 元编程的赶脚...从这个方法也可以看出来 javascript 是一个 runtime 语言) | |
Object.defineProperty( | |
duan, "age", { | |
value: 1, | |
configurable: true, | |
writable: true | |
} | |
) | |
duan.age = 1 | |
//注意: 属性不能同时定义访问器和(赋值 OR 定义 writable) | |
Object.defineProperties( | |
duan, | |
{ | |
'name': { | |
value: 'Duan hong bing', //属性值 | |
writable: true, //属性的值是否可以改。 | |
configurable: true, //配置是否可以改 | |
enumerable: true //是否能在for…in循环中遍历出来或在Object.keys中列举出来 | |
}, | |
'age': { | |
value: 10, | |
configurable: true, //配置是否可以改 | |
enumerable: true //是否能在for…in循环中遍历出来或在Object.keys中列举出来 | |
} | |
} | |
); | |
Object.defineProperties( | |
duan, | |
{ | |
'age': { | |
get: function(){ //get | |
return age; | |
}, | |
set: function(value) { //set | |
age = value + 1; | |
} | |
} | |
} | |
); | |
duan.age = 10; //调用 set | |
alert(duan.age);//调用 get | |
//Object.defineProperty 和 Object.defineProperties 的区别: | |
// 1、Object.defineProperties 可以同时定义多个属性 | |
// 分割线 // | |
// 提示: 以下内容需要 prototype 的相关知识 | |
// 分割线 // | |
//用途: | |
//1、属性的配置可以自定义,比如上面的 writable 如果为 false, 那么该属性是无法修改的,可以防止在实例身上发生意外的赋值操作 | |
//2、动态的为对象添加属性,比如 HTML 的 DOM 对象 | |
//3、定义和赋值的区别(很重要): | |
var foobar = {}; | |
//a、定义属性(Definition) 需要使用到这两个函数: Object.defineProperty 和 Object.defineProperties | |
Object.defineProperty(foobar, "name", {value: 'foobar', configurable: true, writable: true}) | |
//如果 foobar 没有 name 这个自身属性,则该函数的作用是给 foobar 添加一个自身属性 name 并赋值, | |
//参数 {value: 'foobar', configurable: true, writable: true} 指定了该属性拥有的特性(可写性,可枚举性等)。 | |
//如果obj已经有了prop这个自身属性,则该函数的作用是修改这个已有属性的特性,当然也包括它的属性值。 | |
//b、赋值(assignment) | |
foobar.name = 'foobar' | |
foobar['email'] = 'foobar@example.com' | |
//如果 foobar 已经有了 name 这个自身属性, 则该表达式的作用就是修改这个 name 属性的值。 | |
//反之,如果 foobar 没有 name 这个自身属性,则该表达式的操作结果就不一定了。首先会查找对象 foobar 的原型链, | |
//(a)、原型链中的所有对象都没有名为 name 的属性 | |
// 则在 foobar 身上新建一个自身属性 name, 新创建的属性拥有默认的属性特性,且把指定的 value 赋值给该属性。 | |
//(b)、原型链中的所有对象存在名为 name 的属性 | |
//(1)、赋值可能会调用原型上的setter,定义会创建一个自身属性 | |
var proto = { //定义一个原型 | |
//PS: 注意一下这种 getter 和 setter 写法,来自于 ES5 | |
//geter: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get, | |
//setter: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set | |
get foo() { | |
console.log("Getter"); | |
return "a"; | |
}, | |
set foo(x) { | |
console.log("Setter: " + x); | |
}, | |
}; | |
//一个空对象obj, 它的原型 proto 有一个名为 foo 的访问器属性 | |
var obj = Object.create(proto); //ES5 提供的 create 方法,其实等同于 https://docs.google.com/document/d/1rixbOVvwgS89IWgdh5Bo6sbzAa1ceM6wQQ4ccYUmbuI/edit#heading=h.fzfhn0qucj59 | |
//如果这个时候在 obj 身上定义一个 foo 属性和添加一个 foo 属性会有什么区别? | |
//a、定义操作, 会在 obj 身上添加一个自身属性 foo, 互不影响 | |
Object.defineProperty(obj, "foo", { value: "b" }); | |
obj.foo //=> 'b' | |
proto.foo //=> 'Getter' \n a | |
//b、赋值操作, 无法正常完成赋值操作 | |
obj.foo = "b" //=> Setter: b 'b' 调用到了原型的 set 方法 | |
obj.foo //=> 'Getter' \n a | |
proto.foo //=> 'Getter' \n a | |
//升级版本(😝): 定义一个只读的访问器属性(只定义一个getter,省略setter), 且开启严格模式("use strict"; http://www.xiabingbao.com/javascript/2015/02/14/javascript-strict/) | |
<script type="text/javascript"> | |
"use strict"; | |
var proto2 = { | |
get bar() { | |
console.log("Getter"); | |
return "a"; | |
}, | |
}; | |
var obj2 = Object.create(proto2); | |
obj2.bar = "b"; | |
</script> | |
//把上面的保存成 html 文档再使用 chrome 打开并查看 console 就会发现 Uncaught TypeError: Cannot set property bar of #<Object> which has only a getter | |
//(2)、原型链中的同名只读属性可能会阻止赋值操作, 但不会阻止定义操作 | |
var proto = Object.defineProperties( | |
{}, | |
{ | |
foo: { // foo属性的特性: | |
value: "a", | |
writable: false, // 只读 | |
configurable: true // 可配置 | |
} | |
}); | |
var obj = Object.create(proto); | |
obj.foo = "b"; | |
obj.foo //=> 'a' //注: 在严格模式下会抛出异常 TypeError: obj.foo is read-only | |
Object.defineProperty( | |
obj, "foo", { | |
value: "b" | |
} | |
) | |
obj.foo //=> 'b' | |
//结论: 如果原型链中存在一个同名的只读属性,则无法通过赋值的方式在原对象上添加这个自身属性,必须使用定义操作才可以.(ES5 规定) | |
//总结: | |
//如果你想创建一个新属性,则使用属性定义 | |
//如果你想该变一个属性的值,则使用属性赋值 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment