- defineProperty configurable writable value enumerable
- get() set()
- defineProperties 定义多个属性
- getOwnPropertyDescriptor 获取对象属性的所存在的权限描述
- 原型对象
- hasOwnProperty 判断对象是否拥有某属性
- in 只要能够访问到属性就返回true
- 判断属性 存在在实例上 还是 存在在原型上
- keys getOwnPropertyNames
- 原型的动态性 - 先实例化后定义原型对象
- 原型对象的问题 - 先定义原型对象后实例化
- this
defineProperty configurable writable value enumerable
- 控制对象内属性的
删
、改
、值
、for in
let obj = {}
Object.defineProperty(obj, 'name', {
writable: false, // name属性禁止修改
value: 'Lee', // name属性的值
configurable: false, // name属性禁止删除
enumerable: false, // name属性禁止被 for in 循环出来
})
console.log(obj); // {name: "Lee"}
// 以下调用均不输出
obj.name = 'Prosper';
console.log(obj);
delete obj.name
console.log(obj);
for (const key in obj) {
console.log(obj);
}
get() set()
let obj = {
_name: 'Lee'
}
Object.defineProperty(obj, 'name', {
get() {
console.log('读取name');
return this._name;
},
set(value){
console.log('修改name');
this._name = value;
}
})
console.log(obj.name, obj); // 读取name Lee {_name: "Lee"}
obj.name = 'Prosper'; // 修改name
console.log(obj.name, obj); // 读取name Prosper {_name: "Prosper"}
defineProperties 定义多个属性
let obj = {}
Object.defineProperties(obj, {
_name: {
value: 'Lee',
},
_sex: {
writable: false,
value: '1',
configurable: false,
enumerable: false,
},
name: {
get() {
console.log('读取name');
return this._name;
},
set(value){
console.log('修改name');
this._name = value;
}
},
})
console.log(obj); // {_name: "Lee", _sex: "1"}
console.log(obj.name); // 读取name Lee
console.log(obj._sex); // 1
getOwnPropertyDescriptor 获取对象属性的所存在的权限描述
let obj = {name: 'Lee'}
let desc = Object.getOwnPropertyDescriptor(obj, 'name');
console.log(desc); // {value: "Lee", writable: true, enumerable: true, configurable: true}
原型对象
// Person
function Person() {}
// Person Prototype
Person.prototype.name = 'Lee';
Person.prototype.sayName = () => {
return this.name;
}
// person1
let person1 = new Person();
// person2
let person2 = new Person();
// 证明:
// 1. Person的prototype === Person Prototype
console.log(Person.prototype); // {name: "Lee", sayName: ƒ, constructor: ƒ}
// 2. Person Prototype的constructor === Person
console.log(Person.prototype.constructor); // ƒ Person() {}
// 3. person1的[[Prototype]] === Person Prototype
console.log(Person.prototype.isPrototypeOf(person1)); // true
console.log(Object.getPrototypeOf(person1)); // {name: "Lee", sayName: ƒ, constructor: ƒ}
// 4. person2的[Prototype]] === Person Prototype
console.log(Person.prototype.isPrototypeOf(person2)); // true
console.log(Object.getPrototypeOf(person2)); // {name: "Lee", sayName: ƒ, constructor: ƒ}
hasOwnProperty 判断对象是否拥有某属性
// Person
function Person() {}
// Person Prototype
Person.prototype.name = 'Lee';
// person
let person = new Person();
console.log(person.name, person.hasOwnProperty('name')); // Lee false
console.log(Person.prototype.name, Person.prototype.hasOwnProperty('name')); // Lee true
in 只要能够访问到属性就返回true
// Person
function Person() {}
// Person Prototype
Person.prototype.name = 'Lee';
// person
let person = new Person();
console.log('say' in person); // false
console.log('name' in person); // true
console.log('name' in Person.prototype); // true
判断属性 存在在实例上 还是 存在在原型上
function hasPrototypeProperty(object, target){
if(object.hasOwnProperty(target)){
console.log(`${target} 存在在实例上`);
return true
}else if(target in object){
console.log(`${target} 存在在原型上`);
return false
}
}
console.log(hasPrototypeProperty(person, 'name')); // 存在在原型上 false
console.log(hasPrototypeProperty(Person, 'name')); // 存在在实例上 true
console.log(hasPrototypeProperty(Person.prototype, 'name')); // 存在在实例上 true
// => 简写方式
// function hasPrototypeProperty(object, target){
// return object.hasOwnProperty(target) && (target in object);
// }
// console.log(hasPrototypeProperty(person, 'name')); // false
// console.log(hasPrototypeProperty(Person, 'name')); // true
// console.log(hasPrototypeProperty(Person.prototype, 'name')); // true
keys getOwnPropertyNames
let obj = {name: 'Lee', age: 24}
console.log(Object.keys(obj)); // ["name", "age"]
function Person(){
this.name = 'Lee';
this.sayName = ()=>{
return this.name;
}
}
Person.prototype.sex = 1;
let person = new Person();
// []
console.log(Object.keys(Person));
// ["length", "name", "arguments", "caller", "prototype"]
console.log(Object.getOwnPropertyNames(Person));
// ["name", "sayName"]
console.log(Object.keys(person));
// ["sex"]
console.log(Object.keys(Person.prototype));
// ["constructor", "sex"]
console.log(Object.getOwnPropertyNames(Person.prototype));
// ["constructor", "sex"]
console.log(Object.getOwnPropertyNames(Object.getPrototypeOf(person)));
原型的动态性 - 先实例化后定义原型对象
-
原型.key = value
function Person1() { }
let person1 = new Person1();
Person1.prototype.constructor = Person1;
Person1.prototype.name = 'Lee';
// ƒ Person1() { } "Lee"
console.log(Person1.prototype.constructor, person1.name);
// true
console.log(Object.getPrototypeOf(person1) === Person1.prototype);
-
原型 = { key: value }
对于person2来讲这样定义并不能让他在原型上找到name,因为当使用{}的时候相当于new Object(), new了一个新的实例,而在person2的实例中自然找不到这个新的
function Person2() { }
let person2 = new Person2();
Person2.prototype = {
constructor: Person2,
name: 'Lee',
}
// ƒ Person2() { } undefined
console.log(Person2.prototype.constructor, person2.name);
// false
console.log(Object.getPrototypeOf(person2) === Person2.prototype);
原型对象的问题 - 先定义原型对象后实例化
- 通过实例对象修改原型上的引用类型数据后,另一个实例访问原型上的数据也发生了改变,因为他们是同一个原型
function Person() { }
Person.prototype = {
constructor: Person,
name: ['Lee', 'Prosper'],
sex: 1
}
let person1 = new Person();
let person2 = new Person();
console.log(person1 === person2); // false
console.log(person1.name === person2.name); // true
person1.name.pop();
console.log(person1.name === person2.name); // true
person1.sex = 0;
console.log(person1.sex === person2.sex); // false
- 解决:让实例自己拥有自己的name属性
function Person() {
this.name = ['Lee', 'Prosper'];
}
Person.prototype = {
constructor: Person,
sex: 1
}
let person1 = new Person();
let person2 = new Person();
console.log(person1 === person2); // false
console.log(person1.name === person2.name); // false
person1.name.pop();
console.log(person1.name === person2.name); // false
person1.sex = 0;
console.log(person1.sex === person2.sex); // false
this
var name = 'Lee'; // 必须是var
var obj = {
name: 'Prosper',
sayName: function(){
return this.name;
}
}
console.log(obj.sayName()); // Prosper
console.log((obj.sayName)); // ƒ (){ return this.name; }
console.log((obj.sayName)()); // Prosper
console.log((obj.sayName = obj.sayName)); // ƒ (){ return this.name; }
console.log((obj.sayName = obj.sayName)()); // Lee 重新赋值改变了this指向