深入JavaScript Day10 - 【重点】原型链、认识O
2022-01-17 本文已影响0人
望穿秋水小作坊
一、原型链、认识Object
1、对于下面代码,描述查找name的过程?(理解原型链是什么)
var obj = {};
console.log(obj.name);
- obj找name属性的时候,会触发[[get]]操作
- 在obj对象内没找到,就会去
obj.__proto__
中查找 - 而
obj.__proto__
也是一个对象,也有__proto__
属性,所以再会去obj.__proto__.__proto__
中查找 - 直到找到顶层原型,这时
__proto__
属性 指向null
,表示未找到,返回undefined
- 上述原型直接形成的链状结构,就是
原型链
![](https://img.haomeiwen.com/i13946897/38d8afc9fe041f97.png)
2、var obj = {}
是一个快速创建对象的语法糖,语法原形是什么?
var obj = new Object()
3、顶层原型到底是谁?如何证明?为什么需要有顶层原型?
- 顶层原型是
Object函数
- 如果没有顶层原型,那么[[get]]操作,就会沿着原型链进入查找的死循环
var obj = {};
console.log(obj.__proto__.__proto__); // null
console.log(obj.__proto__ === Object.prototype); // ture
![](https://img.haomeiwen.com/i13946897/f69a3e995ece539a.png)
4、Object的本质是什么?
- 很多人把它称为《类》,本质上它是函数
- JavaScript中的所有类,本质上都是函数。
console.log(typeof Object); // function
console.log(typeof Object.prototype); // object
console.log(Object.prototype.__proto__); // null
5、Object是所有类的父类吗?
![](https://img.haomeiwen.com/i13946897/523a93b47849a7b4.png)
![](https://img.haomeiwen.com/i13946897/fbe10e243919028e.png)
二、理解继承
1、【重点掌握】绘制下面代码对应的内存图,并且思考打印结果?
this.name = "why";
}
Person.prototype.running = function () {
console.log(this.name + " 在跑步~");
};
function Student() {}
var p = new Person();
Student.prototype = p;
Student.prototype.studying = function () {
console.log(this.name + " 在学习~");
};
var stu1 = new Student();
stu1.no = 100;
stu1.name = "lsp";
console.log(stu1);
console.log(stu1.__proto__);
console.log(stu1.__proto__.__proto__);
console.log(stu1.__proto__ === p);
stu1.studying();
stu1.running();
var stu2 = new Student();
stu2.no = 200;
console.log(stu2);
stu2.studying();
stu2.running();
- 上述代码,在node环境删除
Person { no: 100, name: 'lsp' }
Person { name: 'why', studying: [Function (anonymous)] }
{ running: [Function (anonymous)] }
true
lsp 在学习~
lsp 在跑步~
Person { no: 200 }
why 在学习~
why 在跑步~
![](https://img.haomeiwen.com/i13946897/1e25e2e74ca6b2fd.png)
![](https://img.haomeiwen.com/i13946897/c777ddf8460a907c.png)
2、上面我们实现了继承体系,但是上面体系存在两大问题?
- ①我们在创建Person或者Student的时候,不好传递参数
- ②如果Person里面有个数组属性(引用类型数据),stu1对数组进行push操作,会同时影响到stu2
3、如何解决上述问题呢?
- 【借用构造函数】
Person.call(this, name, friends);
function Person(name, friends) {
this.name = name;
this.friends = friends;
}
Person.prototype.running = function () {
console.log(this.name + " 在跑步~");
};
function Student(name, no, friends) {
Person.call(this, name, friends);
this.no = no;
}
var p = new Person();
Student.prototype = p;
Student.prototype.studying = function () {
console.log(this.name + " 在学习~");
};
var stu1 = new Student("lsp", 100, []);
stu1.friends.push("lucy");
console.log(stu1);
console.log(stu1.friends);
console.log(stu1.__proto__);
console.log(stu1.__proto__.__proto__);
console.log(stu1.__proto__ === p);
stu1.studying();
stu1.running();
var stu2 = new Student("why", 200, []);
console.log(stu2.friends);
console.log(stu2);
stu2.studying();
stu2.running();
- 上述代码输出
Person { name: 'lsp', friends: [ 'lucy' ], no: 100 }
[ 'lucy' ]
Person {
name: undefined,
friends: undefined,
studying: [Function (anonymous)]
}
{ running: [Function (anonymous)] }
true
lsp 在学习~
lsp 在跑步~
[]
Person { name: 'why', friends: [], no: 200 }
why 在学习~
why 在跑步~
![](https://img.haomeiwen.com/i13946897/de33861c37f40f7e.png)
![](https://img.haomeiwen.com/i13946897/38c3299283498d13.png)
4、上述【借用构造函数】存在2大缺点?
- Person函数至少被调用2次
- stu的原型上会多出一下属性,这些属性都是没存在必要的
![](https://img.haomeiwen.com/i13946897/64ce0637e13ebc1c.png)
5、JavaScript实现继承的完整版思路和方案?
![](https://img.haomeiwen.com/i13946897/df51ba2255718f46.png)
![](https://img.haomeiwen.com/i13946897/22332ac03ce63b0d.png)