Skip to content

Instantly share code, notes, and snippets.

@kenyonduan
Last active September 18, 2015 04:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kenyonduan/4667de99d945764dfc1d to your computer and use it in GitHub Desktop.
Save kenyonduan/4667de99d945764dfc1d to your computer and use it in GitHub Desktop.
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