🧑💻进阶!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
属性指向了一个对象,这个对象正是调用该构造函数而创建的实例的原型,也就是这个例子中的person1
和person2
的原型
(面试题)什么是原型?
答案:每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性
三、_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!
(面试题)那么该怎么表示实例与实例原型,也就是
person
和Person.prototype
之间的关系呢?答案:每个JS对象(除了null)都具有一个属性,叫一个
_proto_
,这个属性会指向该对象的原型。
四、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 -
当删除了
person
的name
属性,读取person.name
,从person
对象找不到name
属性就会从person
的原型,也就是person._proto_
,也即是Person
。prototype
中查找,结果为howiecong
六、原型的原型
var obj= new Object();
obj.name = 'howiecong'
console.log(obj.name)// howiecong
(面试题)如果在原型上还没找到?原型的原型又是什么?
答案:原型对象是通过Object构造函数生产的,实例的
_proto_
指向构造函数prototype
七、原型链
//Object.prototpe的原型为null
console.log(Object.prototype._proto_ === null)//true
(面试题) null 代表什么?
答案:
null
表示没有对象,该处不应该有值,Object.prototype._proto_
的值为null
跟Object.prototype
没有原型,是同个意思,查找到属性的时候查到Object.prototype
就可以停止查找了
八、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
十一、总结
-
构造函数创建对象:使用
new
调用构造函数可创建实例对象,如通过Person
构造函数创建person
实例,并可传入参数初始化实例属性 -
prototype 属性:每个函数都有
prototype
属性,它指向调用该构造函数所创建实例的原型。可在原型上定义属性和方法,被所有实例共享 -
__proto__
属性:除null
外,每个 JS 对象都有__proto__
属性,指向该对象的原型。不过它是非标准属性,建议使用Object.getPrototypeOf()
和Object.setPrototypeOf()
替代 -
constructor 属性:原型对象的
constructor
属性指向关联的构造函数。当实例对象本身没有constructor
属性时,会从原型中读取 -
实例与原型的关系:当访问实例对象的属性时,先在实例本身查找,若未找到则从其原型(
__proto__
指向的对象)中查找 -
原型链:原型对象也有自己的原型,以此类推形成原型链。
Object.prototype
的__proto__
为null
,表示原型链的终点,查找属性时到Object.prototype
即可停止 -
继承:JavaScript的继承并非复制操作,而是在对象间创建关联,通过委托访问其他对象的属性和方法
❓其他
1. 疑问与作者HowieCong声明
-
如有疑问、出错的知识,请及时点击下方链接添加作者HowieCong的其中一种联系方式或发送邮件到下方邮箱告知作者HowieCong
-
若想让作者更新哪些方面的技术文章或补充更多知识在这篇文章,请及时点击下方链接添加里面其中一种联系方式或发送邮件到下方邮箱告知作者HowieCong
-
声明:作者HowieCong目前只是一个前端开发小菜鸟,写文章的初衷只是全面提高自身能力和见识;如果对此篇文章喜欢或能帮助到你,麻烦给作者HowieCong点个关注/给这篇文章点个赞/收藏这篇文章/在评论区留下你的想法吧,欢迎大家来交流!