JS粗读笔记(乱七八糟一锅炖版四)

console对象
table()
对于某些复合类型的数据, console.table方法可以将其转为表格显示。
var languages = [ { name: "JavaScript", fileExtension: ".js" }, { name: "TypeScript", fileExtension: ".ts" }, { name: "CoffeeScript", fileExtension: ".coffee" }];console.table(languages);
上面代码的 language变量,转为表格显示如下。
(index) name fileExtension
0 “JavaScript” “.js”
1 “TypeScript” “.ts”
2 “CoffeeScript” “.coffee”
复合型数据转为表格显示的条件是,必须拥有主键。对于数组来说,主键就是数字键。对于对象来说,主键就是它的最外层键。
count()
count方法用于计数,输出它被调用了多少次。
function greet(user) {  console.count();  return 'hi ' + user;}greet('bob')//  : 1// "hi bob"greet('alice')//  : 2// "hi alice"greet('bob')//  : 3// "hi bob"

上面代码每次调用 greet 函数,内部的 console.count 方法就输出执行次数。
该方法可以接受一个字符串作为参数,作为标签,对执行次数进行分类。
dir(),dirxml()
dir方法用来对一个对象进行检查(inspect),并以易于阅读和打印的格式显示。
console.log({f1: 'foo', f2: 'bar'})// Object {f1: "foo", f2: "bar"}console.dir({f1: 'foo', f2: 'bar'})// Object//   f1: "foo"//   f2: "bar"//   __proto__: Object

上面代码显示 dir 方法的输出结果,比 log 方法更易读,信息也更丰富。
该方法对于输出DOM对象非常有用,因为会显示DOM对象的所有属性。
console.dir(document.body)

dirxml 方法主要用于以目录树的形式,显示DOM节点。
console.dirxml(document.body)

如果参数不是DOM节点,而是普通的JavaScript对象, console.dirxml 等同于 console.dir
assert()
assert方法接受两个参数,第一个参数是表达式,第二个参数是字符串。只有当第一个参数为 false,才会输出第二个参数,否则不会有任何结果。
console.assert(true === false, '判断条件不成立')// Assertion failed: 判断条件不成立

time(),timeEnd()
这两个方法用于计时,可以算出一个操作所花费的准确时间。
console.time('Array initialize');<span style="white-space:pre">											</span>       var array= new Array(1000000);<span style="white-space:pre">												</span>          for (var i = array.length - 1; i >= 0; i--) {    <span style="white-space:pre">										</span>array[i] = new Object();};<span style="white-space:pre">												</span>console.timeEnd('Array initialize');// Array initialize: 1914.481ms

time方法表示计时开始,timeEnd方法表示计时结束。它们的参数是计时器的名称。调用timeEnd方法之后,console窗口会显示“计时器名称: 所耗费的时间”。
profile(),profileEnd()
console.profile方法用来新建一个性能测试器(profile),它的参数是性能测试器的名字。
console.profile('p')// Profile 'p' started.
console.profileEnd方法用来结束正在运行的性能测试器。
console.profileEnd()// Profile 'p' finished.


打开浏览器的开发者工具,在 profile面板中,可以看到这个性能调试器的运行结果
group(),groupend(),groupCollapsed()
console.groupconsole.groupend这两个方法用于将显示的信息分组。它只在输出大量信息时有用,分在一组的信息,可以用鼠标折叠/展开。
console.group('Group One');<span style="white-space:pre">												</span>       console.group('Group Two');// <span style="white-space:pre">												</span>       some codeconsole.groupEnd(); // Group Two 结束console.groupEnd(); // Group One 结束

console.groupCollapsed 方法与 console.group 方法很类似,唯一的区别是该组的内容,在第一次显示时是收起的(collapsed),而不是展开的。

属性描述对象
Object.getOwnPropertyDescriptor()
Object.getOwnPropertyDescriptor方法可以读出对象自身属性的属性描述对象。
var o = { p: 'a' };
Object.getOwnPropertyDescriptor(o, 'p')<span style="white-space:pre">												</span>// Object { value: "a",//   writable: true,//   enumerable: true,//   configurable: true// }


上面代码表示,使用 Object.getOwnPropertyDescriptor方法,读取 o对象的 p属性的属性描述对象。
Object.defineProperty(),Object.defineProperties()
Object.defineProperty方法允许通过定义属性描述对象,来定义或修改一个属性,然后返回修改后的对象。它的格式如下。
Object.defineProperty(object, propertyName, attributesObject)
上面代码中, Object.defineProperty方法接受三个参数,第一个是属性所在的对象,第二个是属性名(它应该是一个字符串),第三个是属性的描述对象。比如,新建一个 o对象,并定义它的 p属性,写法如下。
var o = Object.defineProperty({}, 'p', {  value: 123,  writable: false,  enumerable: true,  configurable: false});<span style="white-space:pre">		</span>o.p// 123o.p = 246;o.p// 123// 因为writable为false,所以无法改变该属性的值

如果一次性定义或修改多个属性,可以使用 Object.defineProperties 方法。
var o = Object.defineProperties({}, {  p1: { value: 123, enumerable: true },  p2: { value: 'abc', enumerable: true },  p3: { get: function () { return this.p1 + this.p2 },    enumerable:true,    configurable:true  }});
o.p1 // 123o.p2 // "abc"o.p3 // "123abc"<span style="color:#ff0000;">
</span>

这时需要注意的是,一旦定义了取值函数
get (或存值函数 set ),就不能将 writable 设为 true ,或者同时定义 value 属性,会报错。

如果一个属性的 enumerablefalse,下面三个操作不会取到该属性。
  • for..in循环
  • Object.keys方法
  • JSON.stringify方法
Object.getOwnPropertyNames()
Object.getOwnPropertyNames方法返回直接定义在某个对象上面的全部属性的名称,而不管该属性是否可枚举。
var o = Object.defineProperties({}, {  p1: { value: 1, enumerable: true },  p2: { value: 2, enumerable: false }});Object.getOwnPropertyNames(o)// ["p1", "p2"]


Object.prototype.propertyIsEnumerable()
对象实例的 propertyIsEnumerable方法用来判断一个属性是否可枚举。
属性描述对象
概述
JavaScript提供了一个内部数据结构,用来描述一个对象的属性的行为,控制它的行为。这被称为“属性描述对象”(attributes object)。每个属性都有自己对应的属性描述对象,保存该属性的一些元信息。
下面是属性描述对象的一个实例。
{  value: 123,  writable: false,  enumerable: true,  configurable: false,  get: undefined,  set: undefined}

属性描述对象提供6个元属性。
(1) value
value存放该属性的属性值,默认为 undefined
(2) writable
writable存放一个布尔值,表示属性值(value)是否可改变,默认为 true
(3) enumerable
enumerable存放一个布尔值,表示该属性是否可枚举,默认为 true。如果设为 false,会使得某些操作(比如 for...in循环、 Object.keys())跳过该属性。
(4) configurable
configurable存放一个布尔值,表示“可配置性”,默认为 true。如果设为 false,将阻止某些操作改写该属性,比如,无法删除该属性,也不得改变该属性的属性描述对象( value属性除外)。也就是说, configurable属性控制了属性描述对象的可写性。
(5) get
get存放一个函数,表示该属性的取值函数(getter),默认为 undefined
(6) set
set存放一个函数,表示该属性的存值函数(setter),默认为 undefined
Object.getOwnPropertyDescriptor()
Object.getOwnPropertyDescriptor方法可以读出对象自身属性的属性描述对象。
var o = { p: 'a' };<span style="white-space:pre">													</span>       Object.getOwnPropertyDescriptor(o, 'p')<span style="white-space:pre">												</span>// Object { value: "a",//   writable: true,//   enumerable: true,//   configurable: true// }


上面代码表示,使用 Object.getOwnPropertyDescriptor方法,读取 o对象的 p属性的属性描述对象。
Object.defineProperty(),Object.defineProperties()
Object.defineProperty方法允许通过定义属性描述对象,来定义或修改一个属性,然后返回修改后的对象。它的格式如下。
Object.defineProperty(object, propertyName, attributesObject)

上面代码中, Object.defineProperty 方法接受三个参数,第一个是属性所在的对象,第二个是属性名(它应该是一个字符串),第三个是属性的描述对象。比如,新建一个 o 对象,并定义它的 p 属性,写法如下。
var o = Object.defineProperty({}, 'p', {  value: 123,  writable: false,  enumerable: true,  configurable: false});o.p// 123o.p = 246;o.p// 123// 因为writable为false,所以无法改变该属性的值


如果属性已经存在, Object.defineProperty方法相当于更新该属性的属性描述对象。
需要注意的是, Object.defineProperty方法和后面的 Object.defineProperties方法,都有性能损耗,会拖慢执行速度,不宜大量使用。
如果一次性定义或修改多个属性,可以使用 Object.defineProperties方法。
var o = Object.defineProperties({}, {  p1: { value: 123, enumerable: true },  p2: { value: 'abc', enumerable: true },  p3: { get: function () { return this.p1 + this.p2 },    enumerable:true,    configurable:true  }});o.p1 // 123o.p2 // "abc"o.p3 // "123abc"


上面代码中的 p3属性,定义了取值函数 get。这时需要注意的是,一旦定义了取值函数 get(或存值函数 set),就不能将 writable设为 true,或者同时定义 value属性,会报错。
var o = {};Object.defineProperty(o, 'p', {  value: 123,  get: function() { return 456; }});// TypeError: Invalid property.// A property cannot both have accessors and be writable or have a value,


上面代码同时定义了 get属性和 value属性,结果就报错。
Object.defineProperty()Object.defineProperties()的第三个参数,是一个属性对象。它的 writableconfigurableenumerable这三个属性的默认值都为 false
var obj = {};Object.defineProperty(obj, 'foo', { configurable: true });Object.getOwnPropertyDescriptor(obj, 'foo')// {//   value: undefined,//   writable: false,//   enumerable: false,//   configurable: true// }


上面代码中,定义 obj对象的 foo属性时,只定义了可配置性 configurabletrue。结果,其他元属性都是默认值。
writable属性为 false,表示对应的属性的值将不得改写。
var o = {};Object.defineProperty(o, 'p', {  value: "bar"});o.p // baro.p = 'foobar';o.p // barObject.defineProperty(o, 'p', {  value: 'foobar',});// TypeError: Cannot redefine property: p


上面代码由于 writable属性默认为 false,导致无法对 p属性重新赋值,但是不会报错(严格模式下会报错)。不过,如果再一次使用 Object.defineProperty方法对 value属性赋值,就会报错。
configurable属性为 false,将无法删除该属性,也无法修改 attributes对象( value属性除外)。
var o = {};Object.defineProperty(o, 'p', {  value: 'bar',});delete o.po.p // "bar"

上面代码中,由于 configurable 属性默认为 false ,导致无法删除某个属性。
enumerable属性为 false,表示对应的属性不会出现在 for...in循环和 Object.keys方法中。
var o = {  p1: 10,  p2: 13,};<span style="white-space:pre">													</span>Object.defineProperty(o, 'p3', {  value: 3,});for (var i in o) {  console.log(i, o[i]);}// p1 10// p2 13


上面代码中, p3属性是用 Object.defineProperty方法定义的,由于 enumerable属性默认为 false,所以不出现在 for...in循环中。
元属性
属性描述对象的属性,被称为“元属性”,因为它可以看作是控制属性的属性。
可枚举性(enumerable)
JavaScript的最初版本, in 运算符和基于它的 for...in循环,会遍历对象实例的所有属性,包括继承的属性。
var obj = {};'toString' in obj // true
上面代码中, toString不是 obj对象自身的属性,但是 in运算符也返回 true,导致被 for...in循环遍历,这显然不太合理。后来就引入了“可枚举性”这个概念,只有可枚举的属性,才会被 for...in循环遍历,同时还规定原生继承的属性都是不可枚举的,这样就保证了 for...in循环的可用性。
可枚举性(enumerable)用来控制所描述的属性,是否将被包括在 for...in循环之中。具体来说,如果一个属性的 enumerablefalse,下面三个操作不会取到该属性。
  • for..in循环
  • Object.keys方法
  • JSON.stringify方法
因此, enumerable可以用来设置“秘密”属性。
var o = {a: 1, b: 2};o.c = 3;Object.defineProperty(o, 'd', { value: 4, enumerable: false});o.d // 4for (var key in o) { console.log(o[key]);}// 1// 2// 3Object.keys(o) // ["a", "b", "c"]JSON.stringify(o) // "{a:1, b:2, c:3}"
上面代码中, d属性的 enumerablefalse,所以一般的遍历操作都无法获取该属性,使得它有点像“秘密”属性,但不是真正的私有属性,还是可以直接获取它的值。
基本上,JavaScript原生提供的属性都是不可枚举的,用户自定义的属性都是可枚举的。
与枚举性相关的几个操作的区别的是, for...in循环包括继承自原型对象的属性, Object.keys方法只返回对象本身的属性。如果需要获取对象自身的所有属性,不管是否可枚举,可以使用 Object.getOwnPropertyNames方法,详见下文。
考虑到 JSON.stringify方法会排除 enumerablefalse的值,有时可以利用这一点,为对象添加注释信息。
var car = {  id: 123,  color: 'red',  ownerId: 12};<span style="white-space:pre">										</span>var owner = {  id: 12,  name: 'Jack'};<span style="white-space:pre">											</span>Object.defineProperty(car, 'ownerInfo', {  value: owner,  enumerable: false});<span style="white-space:pre">						</span>car.ownerInfo// {id: 12, name: "Jack"}JSON.stringify(car)//  "{"id": 123,"color": "red","ownerId": 12}"


上面代码中, owner对象作为注释部分,加入 car对象。由于 ownerInfo属性不可枚举,所以 JSON.stringify方法最后输出 car对象时,会忽略 ownerInfo属性。
这提示我们,如果你不愿意某些属性出现在JSON输出之中,可以把它的 enumerable属性设为 false
可配置性(configurable)
可配置性(configurable)决定了是否可以修改属性描述对象。也就是说,当 configurablefalse的时候,value、writable、enumerable和configurable都不能被修改了。
var o = Object.defineProperty({}, 'p', {  value: 1,  writable: false,  enumerable: false,  configurable: false});Object.defineProperty(o,'p', {value: 2})// TypeError: Cannot redefine property: pObject.defineProperty(o,'p', {writable: true})// TypeError: Cannot redefine property: pObject.defineProperty(o,'p', {enumerable: true})// TypeError: Cannot redefine property: pObject.defineProperties(o,'p',{configurable: true})// TypeError: Cannot redefine property: p


上面代码首先定义对象 o,并且定义 o的属性 pconfigurablefalse。然后,逐一改动 valuewritableenumerableconfigurable,结果都报错。
需要注意的是, writable只有在从 false改为 true会报错,从 true改为 false则是允许的。
var o = Object.defineProperty({}, 'p', {  writable: true,  configurable: false});Object.defineProperty(o,'p', {writable: false})// 修改成功


至于 value,只要 writableconfigurable有一个为 true,就允许改动。
var o1 = Object.defineProperty({}, 'p', {  value: 1,  writable: true,  configurable: false});Object.defineProperty(o1,'p', {value: 2})// 修改成功var o2 = Object.defineProperty({}, 'p', {  value: 1,  writable: false,  configurable: true});Object.defineProperty(o2,'p', {value: 2})// 修改成功


另外, configurablefalse时,直接对该属性赋值,不报错,但不会成功。
var o = Object.defineProperty({}, 'p', {  value: 1,  configurable: false});o.p = 2;o.p // 1

上面代码中, o 对象的 p 属性是不可配置的,对它赋值是不会生效的。
可配置性决定了一个变量是否可以被删除(delete)。
var o = Object.defineProperties({}, {  p1: { value: 1, configurable: true },  p2: { value: 2, configurable: false }});delete o.p1 // truedelete o.p2 // falseo.p1 // undefinedo.p2 // 2


上面代码中的对象 o有两个属性, p1是可配置的, p2是不可配置的。结果, p2就无法删除。
需要注意的是,当使用 var命令声明变量时,变量的 configurablefalse
var a1 = 1;Object.getOwnPropertyDescriptor(this,'a1')// Object {//  value: 1,//  writable: true,//  enumerable: true,//  configurable: false// }


而不使用 var命令声明变量时(或者使用属性赋值的方式声明变量),变量的可配置性为 true
a2 = 1;Object.getOwnPropertyDescriptor(this,'a2')// Object {//  value: 1,//  writable: true,//  enumerable: true,//  configurable: true// }// 或者写成window.a3 = 1;Object.getOwnPropertyDescriptor(window, 'a3')// Object {//  value: 1,//  writable: true,//  enumerable: true,//  configurable: true// }


上面代码中的 this.a3 = 1a3 = 1是等价的写法。 window指的是浏览器的顶层对象。
这种差异意味着,如果一个变量是使用 var命令生成的,就无法用 delete命令删除。也就是说, delete只能删除对象的属性。
var a1 = 1;a2 = 1;delete a1 // falsedelete a2 // truea1 // 1a2 // ReferenceError: a2 is not defined<strong>
</strong>

可写性(writable)
可写性(writable)决定了属性的值(value)是否可以被改变。
var o = {};Object.defineProperty(o, 'a', {  value: 37,  writable: false});o.a // 37o.a = 25;o.a // 37

上面代码将 o 对象的 a 属性可写性设为 false ,然后改变这个属性的值,就不会有任何效果。
注意,正常模式下,对可写性为 false的属性赋值不会报错,只会默默失败。但是,严格模式下会报错,即使是对 a属性重新赋予一个同样的值。
关于可写性,还有一种特殊情况。就是如果原型对象的某个属性的可写性为 false,那么派生对象将无法自定义这个属性。
var proto = Object.defineProperty({}, 'foo', {  value: 'a',  writable: false});var o = Object.create(proto);o.foo = 'b';o.foo // 'a'


上面代码中,对象 protofoo属性不可写,结果 proto的派生对象 o,也不可以再自定义这个属性了。在严格模式下,这样做还会抛出一个错误。但是,有一个规避方法,就是通过覆盖属性描述对象,绕过这个限制,原因是这种情况下,原型链会被完全忽视。
Object.defineProperty(o, 'foo', {  value: 'b'});o.foo // 'b'

Object.getOwnPropertyNames()
Object.getOwnPropertyNames方法返回直接定义在某个对象上面的全部属性的名称,而不管该属性是否可枚举。
var o = Object.defineProperties({}, {  p1: { value: 1, enumerable: true },  p2: { value: 2, enumerable: false }});Object.getOwnPropertyNames(o)// ["p1", "p2"]
一般来说,系统原生的属性(即非用户自定义的属性)都是不可枚举的。
// 比如,数组实例自带length属性是不可枚举的Object.keys([]) // []Object.getOwnPropertyNames([]) // [ 'length' ]// Object.prototype对象的自带属性也都是不可枚举的Object.keys(Object.prototype) // []Object.getOwnPropertyNames(Object.prototype)// ['hasOwnProperty',//  'valueOf',//  'constructor',//  'toLocaleString',//  'isPrototypeOf',//  'propertyIsEnumerable',//  'toString']


上面代码可以看到,数组的实例对象( [])没有可枚举属性,不可枚举属性有length;Object.prototype对象也没有可枚举属性,但是有不少不可枚举属性。
Object.prototype.propertyIsEnumerable()
对象实例的 propertyIsEnumerable方法用来判断一个属性是否可枚举。
var o = {};o.p = 123;o.propertyIsEnumerable('p') // trueo.propertyIsEnumerable('toString') // false
上面代码中,用户自定义的 p属性是可枚举的,而继承自原型对象的 toString属性是不可枚举的。
存取器(accessor)
除了直接定义以外,属性还可以用存取器(accessor)定义。其中,存值函数称为 setter,使用 set命令;取值函数称为 getter,使用 get命令。
存取器提供的是虚拟属性,即该属性的值不是实际存在的,而是每次读取时计算生成的。利用这个功能,可以实现许多高级特性,比如每个属性禁止赋值。
var o = {  get p() {    return 'getter';  },  set p(value) {    console.log('setter: ' + value);  }};

上面代码中, o 对象内部的 get set 命令,分别定义了 p 属性的取值函数和存值函数。定义了这两个函数之后,对 p 属性取值时,取值函数会自动调用;对 p 属性赋值时,存值函数会自动调用。
o.p // "getter"o.p = 123 // "setter: 123"

注意,取值函数Getter不能接受参数,存值函数Setter只能接受一个参数(即属性的值)。另外,对象也不能有与取值函数同名的属性。比如,上面的对象 o 设置了取值函数 p 以后,就不能再另外定义一个 p 属性。
存取器往往用于,属性的值需要依赖对象内部数据的场合。
利用存取器,可以实现数据对象与DOM对象的双向绑定。

Object.preventExtensions()
Object.preventExtensions方法可以使得一个对象无法再添加新的属性。
不过,对于使用了 preventExtensions方法的对象,可以用 delete命令删除它的现有属性。
Object.isExtensible()
Object.isExtensible方法用于检查一个对象是否使用了 Object.preventExtensions方法。也就是说,检查是否可以为一个对象添加属性。
var o = new Object();Object.isExtensible(o) // trueObject.preventExtensions(o);Object.isExtensible(o) <strong>
</strong>

Object.seal()
Object.seal方法使得一个对象既无法添加新属性,也无法删除旧属性。
Object.seal实质是把属性描述对象的 configurable属性设为 false,因此属性描述对象不再能改变了。
同样是使用了 Object.seal方法,如果 writable原为 false,改变这个设置将报错;如果原为 true,则不会有问题。
Object.isSealed()
Object.isSealed方法用于检查一个对象是否使用了 Object.seal方法。
Object.freeze()
Object.freeze方法可以使得一个对象无法添加新属性、无法删除旧属性、也无法改变属性的值,使得这个对象实际上变成了常量。
Object.isFrozen()
Object.isFrozen方法用于检查一个对象是否使用了 Object.freeze()方法

prototype 对象
Object.getPrototypeOf()
Object.getPrototypeOf方法返回一个对象的原型。这是获取原型对象的标准方法
// 空对象的原型是Object.prototypeObject.getPrototypeOf({}) === Object.prototype// true// 函数的原型是Function.prototypefunction f() {}Object.getPrototypeOf(f) === Function.prototype// true// f 为 F 的实例对象,则 f 的原型是 F.prototypevar f = new F();Object.getPrototypeOf(f) === F.prototype// true<strong style="font-size: 24px; line-height: 1.5; white-space: pre-wrap;">
</strong>

Object.setPrototypeOf()
Object.setPrototypeOf方法可以为现有对象设置原型,返回一个新对象。
Object.setPrototypeOf方法接受两个参数,第一个是现有对象,第二个是原型对象
Object.create()
Object.create方法用于从原型对象生成新的实例对象,可以替代 new命令。
它接受一个对象作为参数,返回一个新对象,后者完全继承前者的属性,即原有对象成为新对象的原型
var A = { print: function () { console.log('hello'); }};var B = Object.create(A);B.print() // helloB.print === A.print // true


上面代码中, Object.create方法在 A的基础上生成了 B。此时, A就成了 B的原型, B就继承了 A的所有属性和方法。

下面三种方式生成的新对象是等价的。
var o1 = Object.create({});var o2 = Object.create(Object.prototype);var o3 = new Object();


除了对象的原型, Object.create方法还可以接受第二个参数。该参数是一个属性描述对象,它所描述的对象属性,会添加到新对象。
var o = Object.create({}, { p1: { value: 123, enumerable: true }, p2: { value: 'abc', enumerable: true }});// 等同于var o = Object.create({});o.p1 = 123;o.p2 = 'abc';


Object.create方法生成的对象,继承了它的原型对象的构造函数

function A() {}var a = new A();var b = Object.create(a);b.constructor === A // trueb instanceof A // true

上面代码中, b 对象的原型是 a 对象,因此继承了 a 对象的构造函数 A
Object.prototype.isPrototypeOf()
对象实例的 isPrototypeOf方法,用来判断一个对象是否是另一个对象的原型。
var o1 = {};var o2 = Object.create(o1);var o3 = Object.create(o2);o2.isPrototypeOf(o3) // trueo1.isPrototypeOf(o3) // true

上面代码表明,只要某个对象处在原型链上, isProtypeOf 都返回 true
Object.prototype.__proto__
__proto__属性(前后各两个下划线)可以改写某个对象的原型对象。
var obj = {};var p = {};obj.__proto__ = p;Object.getPrototypeOf(obj) === p // true

上面代码通过 __proto__ 属性,将 p 对象设为 obj 对象的原型。
根据语言标准, __proto__属性只有浏览器才需要部署,其他环境可以没有这个属性,而且前后的两根下划线,表示它本质是一个内部属性,不应该对使用者暴露。因此,应该尽量少用这个属性,而是用 Object.getPrototypeof()(读取)和 Object.setPrototypeOf()(设置),进行原型对象的读写操作。

推荐使用第三种 Object.getPrototypeOf方法,获取原型对象。

Object 对象与继承
对象本身的属性之中,有的是可以枚举的(enumerable),有的是不可以枚举的, Object.getOwnPropertyNames方法返回所有键名。只获取那些可以枚举的属性,使用 Object.keys方法。
Object.prototype.hasOwnProperty()
对象实例的 hasOwnProperty方法返回一个布尔值,用于判断某个属性定义在对象自身,还是定义在原型链上。
Date.hasOwnProperty('length')// trueDate.hasOwnProperty('toString')// false

hasOwnProperty 方法是JavaScript之中唯一一个处理对象属性时,不会遍历原型链的方法。

in 运算符和 for…in 循环
in运算符返回一个布尔值,表示一个对象是否具有某个属性。它不区分该属性是对象自身的属性,还是继承的属性。
'length' in Date // true'toString' in Date // true
in运算符常用于检查一个属性是否存在。

对象的拷贝
如果要拷贝一个对象,需要做到下面两件事情。
  • 确保拷贝后的对象,与原对象具有同样的prototype原型对象。
  • 确保拷贝后的对象,与原对象具有同样的属性。
下面就是根据上面两点,编写的对象拷贝的函数。
function copyObject(orig) { var copy = Object.create(Object.getPrototypeOf(orig)); copyOwnPropertiesFrom(copy, orig); return copy;}function copyOwnPropertiesFrom(target, source) { Object .getOwnPropertyNames(source) .forEach(function(propKey) { var desc = Object.getOwnPropertyDescriptor(source, propKey); Object.defineProperty(target, propKey, desc); }); return target;}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值