⛽进阶!JavaScript核心概念篇1——原型&原型链

922 阅读5分钟

🧑‍💻进阶!JavaScript核心概念篇1——原型&原型链-HowieCong

一、构造函数创建对象

function Person(name, age) {
    this.name = name;
    this.age = age;
}

var person = new Person('howiecong', 21);
console.log(person.name); // howiecong
console.log(person.age); // 21
  • Person就是一个构造函数,使用new创建一个实例对象person

二、prototype

function Person(){

}
// prototype是函数才会有的属性
Person.prototype.name = 'howiecong';


Person.prototype.sayHello = function() {
    console.log('Hello!');
};

var person1 = new Person();
var person2 = new Person();

console.log(person1.name)//howiecong
console.log(person2.name)//howiecong

person1.sayHello(); // Hello!
person2.sayHello(); // Hello!
  • 每个函数都有一个prototype

  • 函数的 prototype 属性指向了一个对象,这个对象正是调用该构造函数而创建的实例的原型,也就是这个例子中的 person1person2 的原型

(面试题)什么是原型?

答案:每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性

image.png

三、_proto_

function Person(){

}
var person = new Person();

console.log(person._proto_ === Person.prototype)//true
  • 关于__proto__的兼容性问题,虽然绝大部分浏览器支持,但它是非标准属性,建议使用Object.getPrototypeOf()Object.setPrototypeOf()方法来替代
function Person() {

}
var person = new Person();

// 使用Object.getPrototypeOf()获取原型
console.log(Object.getPrototypeOf(person) === Person.prototype); // true

// 使用Object.setPrototypeOf()设置原型
var newPrototype = {
    greet: function() {
        console.log('Greetings!');
    }
};
Object.setPrototypeOf(person, newPrototype);
person.greet(); // Greetings!

面试题)那么该怎么表示实例与实例原型,也就是personPerson.prototype之间的关系呢?

答案:每个JS对象(除了null)都具有一个属性,叫一个_proto_,这个属性会指向该对象的原型。

image.png

四、constructor

function Person(){

}
console.log(Person === Person.prototype.constructor);//true

console.log(Person.prototype.constructor == Person)//true

console.log(Object.getPrototypeOf(person) === Person.prototype)//true

(面试题)实例对象和构造函数都可以指向原型,那么原型是否有属性指向构造函数或者实例呢?

答案:指向实例没有,因为一个构造函数可以生成多个实例,但是原型指向构造函数时有的:constructor,每个原型都有一个constructor属性指向关联的构造函数

五、实例与原型

function Person(){

}

Person.prototype.name = 'howiecong';

var person = new Person();

person.name = 'howiecong';
console.log(person.name)//howiecong

delete person.name;
console.log(person.name)//howiecong
  • 给实例对象添加了name属性,打印person.name,结果为howiecong

  • 当删除了personname属性,读取person.name,从person对象找不到name属性就会从person的原型,也就是person._proto_,也即是Personprototype中查找,结果为howiecong

六、原型的原型

var obj= new Object();
obj.name = 'howiecong'
console.log(obj.name)// howiecong

(面试题)如果在原型上还没找到?原型的原型又是什么?

答案:原型对象是通过Object构造函数生产的,实例的_proto_指向构造函数prototype

image.png

七、原型链

//Object.prototpe的原型为null
console.log(Object.prototype._proto_ === null)//true

(面试题) null 代表什么?

答案:null表示没有对象,该处不应该有值,Object.prototype._proto_的值为nullObject.prototype没有原型,是同个意思,查找到属性的时候查到Object.prototype就可以停止查找了

image.png

八、constructor

function Person(){
}
var person = new Person();

console.log(person.constructor === Person);//true
  • 获取person.constructor时,其实person没有constructor属性,当不能读取到constructor属性时,会从person的原型就是Person.prototype中读取,正好原型中有该属性,因此:person.constructor === Person.prototype.constructor

九、proto

  • 绝大部分浏览器都支持这个非标准的方法访问原型,然而它并不存在于Person.prototype,实际上来自于Object.prototype,不如说是一个getter/setter,当使用obj._proto_时,可以理解返回了Object.getPrototypeOf(obj)

十、继承

  • 继承意味着复制操作,然而JS默认不会复制对象的属性,相反,JS只是在两个对象之间创建一个关联,一个对象就可以通过委托访问另一个对象的属性和函数,其实更像委托的说法更准确

  • 几种常见的JavaScript继承方式,如原型链继承、构造函数继承、组合继承、寄生组合继承等

function Animal() {
    this.species = 'Animal';
}

function Cat() {

}
Cat.prototype = new Animal();

var cat = new Cat();
console.log(cat.species); // Animal

十一、总结

  1. 构造函数创建对象:使用new调用构造函数可创建实例对象,如通过Person构造函数创建person实例,并可传入参数初始化实例属性

  2. prototype 属性:每个函数都有prototype属性,它指向调用该构造函数所创建实例的原型。可在原型上定义属性和方法,被所有实例共享

  3. __proto__属性:除null外,每个 JS 对象都有__proto__属性,指向该对象的原型。不过它是非标准属性,建议使用Object.getPrototypeOf()Object.setPrototypeOf()替代

  4. constructor 属性:原型对象的constructor属性指向关联的构造函数。当实例对象本身没有constructor属性时,会从原型中读取

  5. 实例与原型的关系:当访问实例对象的属性时,先在实例本身查找,若未找到则从其原型(__proto__指向的对象)中查找

  6. 原型链:原型对象也有自己的原型,以此类推形成原型链。Object.prototype__proto__null,表示原型链的终点,查找属性时到Object.prototype即可停止

  7. 继承:JavaScript的继承并非复制操作,而是在对象间创建关联,通过委托访问其他对象的属性和方法

❓其他

1. 疑问与作者HowieCong声明

  • 如有疑问、出错的知识,请及时点击下方链接添加作者HowieCong的其中一种联系方式或发送邮件到下方邮箱告知作者HowieCong

  • 若想让作者更新哪些方面的技术文章或补充更多知识在这篇文章,请及时点击下方链接添加里面其中一种联系方式或发送邮件到下方邮箱告知作者HowieCong

  • 声明:作者HowieCong目前只是一个前端开发小菜鸟,写文章的初衷只是全面提高自身能力和见识;如果对此篇文章喜欢或能帮助到你,麻烦给作者HowieCong点个关注/给这篇文章点个赞/收藏这篇文章/在评论区留下你的想法吧,欢迎大家来交流!

2. 作者社交媒体/邮箱-HowieCong