JavaScript高级程序设计(第4版)读书分享笔记记录
适用于刚入门前端的同志
创建Object的实例
let person = new Object();
person.name = "Nicholas";
person.age = 29;
person.job = "Software Engineer";
person.sayName = function() {
console.log(this.name);
};
对象字面量
let Person = {
name:'Tom',
age:28,
job:'Teacher',
sayName(){
console.log(this.name)
}
}
Person.sayName() // Tom
虽然使用 Object 构造函数或对象字面量可以方便地创建对象,但这些方式也有明显不足:创建具有同样接口的多个对象需要重复编写很多代码。
工厂模式
function createPerson(name,age,job){
let o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
console.log(this.name)
}
return o;
}
let person1 = createPerson('Tom',28,'Teacher')
let person2 = createPerson('Jerry',18,'Student')
console.log(person1 ) // {name:'Tom',age:28,job:'Teacher',sayName: ƒ ()}
构造函数模式
function Person(name,age,job){
this.name = name
this.age = age
this.job = job
this.sayName = function(){
console.log(this.name)
}
}
let person1 = new Person('Tom',28,'Teacher')
person1.sayName () //Tom
let person2 = new Person('Jerry',18,'Student')
person1.sayName () //Jerry
工厂模式和构造函数模式的区别:
- 没有显式地创建对象。
- 属性和方法直接赋值给了 this。
- 没有 return
- 创建一个新对象;
- 将构造函数的作用域赋给新对象(使this指向新对象);
- 执行构造函数中的代码(为这个新对象添加属性);
- 返回新对象。
问题:
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = sayName;
}
function sayName() {
console.log(this.name);
}
let person1 = new Person("Nicholas", 29, "Software Engineer");
let person2 = new Person("Greg", 27, "Doctor");
person1.sayName(); // Nicholas
person2.sayName(); // Greg
原型模式
function Person(){}
Person.prototype.name = 'Tom'
Person.prototype.age = 28
Person.prototype.job = 'Teacher'
Person.prototype.sayName = function(){
console.log(this.name)
}
let person1 = new Person()
person1.sayName() // Tom
let person2 = new Person()
person1.sayName() // Tom
console.log(person1.sayName == person2.sayName); // true
理解原型
无论何时,只要创建一个函数,就会按照特定的规则为这个函数创建一个 prototype 属性(指向原型对象)。默认情况下,所有原型对象自动获得一个名为 constructor 的属性,指回与之关联的构 造函数。
前面的例子就可以理解为:
Person.prototype.constructor 指向 Person。
console.log(Person.prototype.constructor === Person); // true
在自定义构造函数时,原型对象默认只会获得 constructor 属性,其他的所有方法都继承自
Object。每次调用构造函数创建一个新实例,这个实例的内部[[Prototype]](__proto__属性)指针就会被赋值为构造函数的原型对象
console.log(Person.prototype.__proto__ === Object.prototype); // true
原型层级
当访问某个实例的属性和方法时,会先在实例上搜索个属性。如果这个属性在实例上存在,所以就不会再搜索原型对象了。而并没有在实例上找到这个属性,所以会继续搜索原型对象并使用定义在原型上的属性。
例子:
function Person() {}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function() {
console.log(this.name);
};
let person1 = new Person();
let person2 = new Person();
person1.name = "Greg";
console.log(person1.name); // "Greg",来自实例
console.log(person2.name); // "Nicholas",来自原型
例子:
function Person() {}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function() {
console.log(this.name);
};
let person1 = new Person();
let person2 = new Person();
person1.name = "Greg";
console.log(person1.name); // "Greg",来自实例
console.log(person2.name); // "Nicholas",来自原型
delete person1.name;
console.log(person1.name); // "Nicholas",来自原型
function Person() {}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function() {
console.log(this.name);
};
let person1 = new Person();
let person2 = new Person();
console.log(person1.hasOwnProperty("name")); // false
person1.name = "Greg";
console.log(person1.name); // "Greg",来自实例
console.log(person1.hasOwnProperty("name")); // true
// 原型对象还是接上面的
let person = new Person();
console.log(hasPrototypeProperty(person, "name")); // true
person.name = "Greg";
console.log(hasPrototypeProperty(person, "name")); // false
Object.keys()
要获得对象上所有可枚举的实例属性
//原型对象接上面的案例
let keys = Object.keys(Person.prototype);
console.log(keys); // "name,age,job,sayName"
let p1 = new Person();
p1.name = "Rob";
p1.age = 31;
let p1keys = Object.keys(p1);
console.log(p1keys); // "[name,age]"
Object.getOwnPropertyNames():
如果想列出所有实例属性,无论是否可以枚举,都可以使用
let keys = Object.getOwnPropertyNames(Person.prototype);
console.log(keys); // "[constructor,name,age,job,sayName]"
对象迭代
ECMAScript 2017 新增了两个静态方法,Object.values()和 Object.entries()接收一个对象
示例:
const o ={
foo: 'bar',
baz: 1,
qux: {}
};
console.log(Object.values(o)); // ["bar", 1, {}]
console.log(Object.entries((o))); // [["foo", "bar"], ["baz", 1], ["qux", {}]]