作为一名工作两年多的前端开发者来说,原型链一直是困扰我的问题。
很震惊吧,作为前端怎么连这么基础的问题都不清楚,怎么找到工作的?
其实一点也不奇怪!
正常工作中前端起到的作用无外乎“搬砖”,需要组件了很少自己写,基本都是“问度娘”。
(大神就算了,当我没说。)
闲来无事,查了很多资料和文档,终于理清了他们之间的关系,特此记录一下。
这里总结一下路线:
- this指向
- 原型链
- class类和原型链关系
一、this指向问题
this指向的永远是调用它的对象。
function a(){
var user = "码农无码";
console.log(this.user); //undefined
console.log(this); //Window
}
a(); // 实际上可以理解为:a() === window.a()
从代码可以看出a方法是被window直接调用的,因此,this指向的是window。
var o = {
user:"码农无码",
fn:function(){
console.log(this.user); // 码农无码
}
}
window.o.fn();
// 通过window --> o --> fn调用,却输出了o的user属性值,为什么呢?
var o = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a); //12
}
}
}
o.b.fn();
// 这里多级嵌套,只输出了a = 12,而不是a=10
如果这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象。
var o = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a); //undefined
console.log(this); //window
}
}
}
var j = o.b.fn;
j();
为什么呢?是不是很奇怪?
切记:this永远指向的是最后调用它的对象
你品,你细品!
j被赋值的时候,方法fn并没有被调用,直接调用者为:window.j(),因此this指向的是window而不是b。
到这里,基本this的指向问题就基本理解差不多了。
二、原型链的理解
原型链最重要的三个属性:prototype、__proto__、constructor
每个构造方法都具备prototype属性,这个属性指向一个对象。
function Person() {
}
// 虽然写在注释里面,但是需要注意的是
// prototype 是函数才会有的属性
Person.prototype.name = "Kevin";
var person1 = new Person();
var person2 = new Person();
console.log(person1.name) // Kevin
console.log(person2.name) // Kevin
每一个JavaScript对象(除了null)都具有的一个属性,叫__proto__,这个属性会指向该对象的原型,即作为实例对象和实例原型的之间的链接桥梁。
function Person() {
}
var person = new Person();
console.log(person.__proto__ === Person.prototype); //true;
function Person() {
}
console.log(Person === Person.prototype.constructor); // true
function Person() {
}
var person = new Person();
console.log(person.__proto__ == Person.prototype) // true
console.log(Person.prototype.constructor == Person) // true
// 顺便学习一个ES5的方法,可以获得对象的原型
console.log(Object.getPrototypeOf(person) === Person.prototype) // true
1.声明了构造函数 Person;
2.使用new操作符调用 Person 实例化了一个person 对象;
3.判断实例化对象通过__proto__是否指向实例原型;
4.判断实例原型通过constructor是否能找到对应的构造函数;
5.使用Object.getPrototypeOf方法传入一个对象 找到对应的原型对象;
三、ES6中class和原型链之间的关系
class User{
constructor(){
console.log('默认调用');
}
eat(){
console.log('eat方法');
}
}
var user = new User();//默认调用
user.eat()//eat方法
等同于:
function User() {}
User.prototype.eat = function () {}
因此可以总结为:
类:User === 构造函数User.protoType(实例原型)
类User的constructor指向构造函数User
简单总结下,如有问题,请指出!
后期有时间继续完善。