-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JS-对象 #54
Comments
操作对象属性一、谈谈属性属性是一个key-value对,key是属性的标识(也叫名字),value是属性的值。 1.1 属性名字:除了可以字符串命名属性名字,还可以是 var a = {
sex: 'M', // 字符串属性名字
[Symbol('age')]: 22 // Symbol属性名字,ES6可计算属性名
}
a[Symbol('n')] = 'john' 1.2 属性值:属性值除了可以用一个具体的JS数据类型值(Data Property)外,还可以用个函数表示(getter/setter属性, Accessor Property),这样可以在get/set时执行一些逻辑。 var count=0;
var obj = {
log: ['a', 'b', 'c'],
get latest() {
console.log(`${++count}`) // 记录get次数
if (this.log.length == 0) {
return undefined;
}
return this.log[this.log.length - 1];
},
set latest(val) {
this.log.push(val)
}
}
console.log(obj.latest)
obj.latest = 'd';
console.log(obj.latest) 1.3 属性的特性属性除了具有名字和值之外还有一些特性,用于描述属性。 1. configurable
即当
1,2,3条其实就是属性的配置信息,所以有个 var a = {};
Object.defineProperty(a, 'b', {
value: 22,
enumerable: true,
writable: true
})
console.log(a.b) // 22
console.log(delete a.b); // false
console.log(a.b) // 22
// update value, OK
Object.defineProperty(a, 'b', {
value: 23,
enumerable: true,
writable: true
})
// update writable, OK
Object.defineProperty(a, 'b', {
writable: false,
enumerable: true
})
// update enumerable, TypeError: Cannot redefine property: b
Object.defineProperty(a, 'b', {
enumerable: !true,
writable: true
})
// update type, TypeError: Cannot redefine property: b
Object.defineProperty(a, 'b', {
get: () => {}
})
2. enumerable是否可枚举。见for-in,Object.keys方法。 3. 数据类型属性( value,writable)
4. getter/setter属性(get, set)
5.
|
遍历对象直接问如何遍历一个对象都是耍流氓,首先要明确遍历哪些属性?
例如express的依赖merge-descriptors源码有这么一段: Object.getOwnPropertyNames(src).forEach(function forEachOwnPropertyName (name) {
if (!redefine && hasOwnProperty.call(dest, name)) {
// Skip descriptor
return
} 遍历对象为啥使用 1. for-in方式最原始的方式估计就是 var hasOwnProperty = Object.prototype.hasOwnProperty;
var a = {
name: 'john',
say: function() {
console.log(a.name)
}
}
var b = Object.create(a, {
age: {
value: 12,
enumerable: true,
writable: true,
configurable: true
},
sex: {
value: 'M',
enumerable: false,
writable: true,
configurable: true
}
})
for(var key in b) {
console.log(`${key}-${hasOwnProperty.call(b, key)}`)
} 1.2 总结
2.
|
对象的三个特性
一、类型信息类型信息可以通过 1.1 类型判断
function isNull(obj){
return obj === null;
}
function isUndefined(obj) {
return obj === void 0;
} 二、可扩展性标记对象是否可以添加新的属性。
2.2 三个级别控制2.2.1 Object.preventExtensions()方法
"use strict"
var p = {
name: 'john'
}
var b = Object.create(p);
Object.preventExtensions(b); // 转成不可扩展的对象
try {
b.age = 22; // 尝试添加新属性
} catch(e) {
console.error(e) // 抛异常:TypeError: Cannot add property age, object is not extensible
}
p.name2 = 12; // 原型可以添加新属性
console.log(p.name2); // 访问原型上的属性
2.2.2 封闭对象 & Object.seal()
"use strict"
var p = {
name: 'john'
}
var b = Object.create(p);
b.age = 22;
console.log(Object.getOwnPropertyDescriptors(b)); //{value: 22, writable: true, enumerable: true, configurable: true}
Object.seal(b);
console.log(Object.getOwnPropertyDescriptors(b)); //{value: 22, writable: true, enumerable: true, configurable: false}
p.name2 = '12' // 原型可以添加新属性
console.log(b.name2) // 访问原型上的属性
2.2.3 冻结对象 & Object.freeze()
简单理解:Object.freeze() = Object.seal() + 将现有属性转成 "use strict"
var p = {
name: 'john'
}
var b = Object.create(p);
b.age = 22;
console.log(Object.getOwnPropertyDescriptors(b)); // {value: 22, writable: true, enumerable: true, configurable: true}
Object.freeze(b);
console.log(Object.getOwnPropertyDescriptors(b)); // {value: 22, writable: false, enumerable: true, configurable: false}
p.name2 = '12' // 原型可以添加新属性
console.log(b.name2) // 访问原型上的属性
三、原型3.1 原型对象继承属性的对象,每个对象内部都有个私有属性([[Prototype]])指向其原型对象,原型对象又有其原型对象,一直到null,这个链构成了原型链。 3.2 原型继承
3.2.2 缺点
3.3 操作原型1. 检测
注意两者的区别。 2. get原型利用
|
练习1. 输出以下代码运行结果// example 1
var a={}, b='123', c=123;
a[b]='b';
a[c]='c';
console.log(a[b]);
// example 2
var a={}, b=Symbol('123'), c=Symbol('123');
a[b]='b';
a[c]='c';
console.log(a[b]);
// example 3
var a={}, b={key:'123'}, c={key:'456'};
a[b]='b';
a[c]='c';
console.log(a[b]); 2. a.b.c.d 和 a['b']['c']['d'],哪个性能更高?性能差异可以忽略。中括号涉及类型转换判断逻辑, |
|
深度Copy的思考一、为啥需要Deep copy ?摘自知乎:JavaScript 如何完整实现深度Clone对象?
二、Deep copy的难点首先明确一点:深copy的目的是为了获取引用类型变量的值。
三、实现方案3.1 DeepCopy不是那么容易实现的针对需要Copy的对象,选择合适的方式。
3.2 常见方式:1.
|
对象
一、概述
JS是一种面向对象的语言。除了基本数据类型number, string, boolean(true, false), null, undefined,其他的都是对象。对象就是一个"name-value"对集合。
二、操作对象
2.1 创建对象
JS有三种创建对象的方式:
2.1.1
Object.create(null | object[, properties])
ES5增加的方法,功能是创建一个对象,并且该对象的原型指向create的参数对象。
null
或者对象),否则报错;null
也是合法的原型值,表示没有原型对象,比如大名顶顶的Object.protototpe
对象就没有原型。用ES3的方式模拟
create
行为create
行为的2.1.2 对象字面量
对象字面量是一种创建对象的便捷方式,见上例。其中对象p的创建方式就是对象字面量。JS解释器会对它进行处理的,等价于:
所以说对象字面量内部也是通过
Object.create
方式创建对象的,并且所有对象字面量方式创建的对象的原型都执行Object.prototype
(如上图)。思考:JS解释器如何区分语句块花括号
{}
和空对象花括号{}
的?先看看这两条语句执行的结果?
{}
作为右值(赋值表达式右侧),实参,在运算符的右侧,被括号()
包裹则作为对象,其他则视为语句块:下面输出都是:"[object Object]"
2.1.3
new
构造方式JS的作者为了讨好类语言的开发者,引入了第三者创建对象方式,即
new
构造方式。这使得JS对象的创建有点像类语言的对象创建。内部原理
这种方式的内部也是通过Object.create方式构建的。new方式创建对象大致分为三步:
2.2 访问对象属性
访问方式也就是
get/set/delete
。在get访问
中会涉及原型链,set/delete访问
不会。2.2.1 Get操作流程:
2.2.2 Set操作流程:
2.2.3 delete操作
2.3 检测属性:
in
&Object.prototype.hasOwnProperty
两者都可以用于检测对象是否含有某个属性。但区别是:
in
会查找对象的原型对象(这个跟for-in
语句一样),而Object.prototype.hasOwnProperty
就像命名一样当然不会。The text was updated successfully, but these errors were encountered: