深入JavaScript Day09 - 隐式原型、显示原型、n
2022-01-15 本文已影响0人
望穿秋水小作坊
一、理解原型、原型链的一些要点【最重要的概念梳理,一定要理解】
1、对函数 function Foo(){} 调用new会发生以下五件事
①创建一个新的空对象
②将新对象的proto属性指向函数的Prototype对象
③将this指针指向新的对象(new 绑定)
④指向函数体代码
⑤如果函数没有明确返回值,则返回新对象
2、关于Object的内容
①Object.prototype.proto === null
②let o = {a:10};是一种语法糖,完整代码是: let o = new Object({a:10});
③因此:o.proto === Object.prototype; o.proto.proto === Object.prototype.proto === null;
3、关于 proto、prototype、constructor 之间关系理解
① proto 凡是对象都有的属性,基本上JavaScript中所有的对象最终都指向 Object.prototype;
② prototype 是函数才拥有的属性,执行代码 let o = new Foo(),会将o.proto指向Foo.prototype;
③ 所有的 prototype 都有一个constructor属性,constructor指向函数对象本身,Foo === o.proto.constructor === o.constructor === Foo.prototype.constructor
4、关于Foo和Function之间的关系的理解
① function Foo() {}
是语法糖 const Foo = new Funciton("xxx")
;因此 Foo.proto === Function.prototype
二、JavaScript创建对象的方式
1、如下创建对象的方式,如果创建100个对象,有什么问题吗?
var p1 = {
name: "张三",
age: 18,
height: 1.88,
eat: function () {
console.log(this.name + "在吃饭~");
},
};
var p2 = {
name: "张三",
age: 17,
height: 1.77,
eat: function () {
console.log(this.name + "在吃饭~");
},
};
console.log(p1);
console.log(p2);
console.log(p1.eat === p2.eat);
- 【问题一】100个对象,就有100份这样对象定义的代码,代码非常冗余;
- 【问题二】100个对象的eat方法,都是不同方法,其实代码执行体是完全一致的,没必要创建100方法对象;
- 【问题三】没有类型提示,所有类型都是Object,太笼统了。
2、通过工厂模式创建对象
function eat() {
console.log(this.name + "在吃饭~");
}
function createPersonFoactory(name, age, height) {
return {
name,
age,
height,
eat,
};
}
var p1 = createPersonFoactory("张三", 18, 1.88);
var p2 = createPersonFoactory("李四", 17, 1.77);
console.log(p1);
console.log(p2);
console.log(p1.eat === p2.eat);
p1.eat();
p2.eat();
- 【优点】解决代码冗余和函数重复定义的问题
- 【缺点】依然没有类型的概念
3、借助构造函数创建对象的方案
![](https://img.haomeiwen.com/i13946897/e08f6f8f3e0f1def.png)
三、构造函数、new、对象的原型
1、构造函数在什么时候自动调用?JavaScript中的构造函数和其他语言有什么不同?
- 【调用】构造函数在对象创建的时候,自动调用。
- 【在其他语言中】构造器是类中的一个方法
- 【在JavaScript中】构造函数只是一个普通的函数,如果这么一个普通的函数被使用new关键字调用,那么它就被称之为构造函数
![](https://img.haomeiwen.com/i13946897/39f00e0d9ac7fa42.png)
2、如果一个函数被使用new操作符调用了,那么它会执行如下操作?
- ①在内存中创建一个新的对象(空对象);
- ②这个对象内部的[[prototype]]属性会被赋值为该构造函数的prototype属性;
- ③构造函数内部的this,会指向创建出来的新对象;(new 绑定);
- ④执行函数的内部代码(函数体代码);
- ⑤如果构造函数没有返回非空对象,则返回创建出来的新对象;
![](https://img.haomeiwen.com/i13946897/cfac15c9f01f27bf.png)
3、认识对象的原型。是所有对象都有原型吗?怎么获取?隐式原型
- 只要是对象都会有这样的一个内置属性[[prototype]]
- 通过【proto】 或者【Object.getPrototypeOf】可以获取到
![](https://img.haomeiwen.com/i13946897/2078d6e92f45bbb4.png)
4、认识函数的原型 prototype。所有函数都有都有prototype吗?显示原型
![](https://img.haomeiwen.com/i13946897/150536e3edceb5e8.png)
5、理解new操作时,对象的隐式原型指向显示原型的过程?
![](https://img.haomeiwen.com/i13946897/88afa9012c05e015.png)
![](https://img.haomeiwen.com/i13946897/3e6c3b75c59a9e7b.png)
![](https://img.haomeiwen.com/i13946897/85da6c55850e87d7.png)
5、理解constructor属性,这个属性存在于哪里,指向谁?
- 默认情况下显示原型都会添加一个属性叫做
constructor
,这个constructor指向当前的函数对象
![](https://img.haomeiwen.com/i13946897/4983bf4e7cd58e66.png)
6、重写显示原型的方式?
![](https://img.haomeiwen.com/i13946897/dab5f10f56af93d9.png)
![](https://img.haomeiwen.com/i13946897/fa0f6f7ead37d9c4.png)
7、如何查看一个属性的属性描述符?
function Person(name) {
this.name = name;
}
var p1 = new Person("zhansan");
var p2 = new Person("lisi");
console.log(p1.__proto__);
console.log(Object.getOwnPropertyDescriptors(p1));
console.log(Object.getOwnPropertyDescriptors(p1.__proto__));
![](https://img.haomeiwen.com/i13946897/fbec2a230e053438.png)