原型与原型链 new实现继承的原理

在典型的面向对象语言中,如java都存在类class的概念,类就是对象的模板,对象就是类的实例。但是在javaScript语言体系中,是不存在类的概念。javaSCript中不是基于类,而是通过构造函数(constructor)和原型链(prototype chains)实现的。

1.构造函数

所谓构造函数,就是提供一个生成对象的模板并描述对象的基本结构的函数。一个构造函数,可以生成多个对象,每个对象都有相同的结构,构造函数就是对象的模板,对象就是构造函数的实例。
但是构造函数有一个缺点就是:同一个构造函数的对象实例之间无法共享属性或方法

2.prototype(原型)

为了解决构造函数的对象实例之间无法共享属性的缺点,javaScript提供了prototype属性。
原型上的所有属性和方法都会被对象实例所共享。
每一个函数都有一个prototype属性,也只有函数有prototype属性

var a = 2;
var a1 = a.prototype; // undefine
var b = {};
var b1 = b.prototype; // undefine
var c = 'fdc';
var c1 = c.prototype; // undefine
var d = function() {};
var d1 = d.prototype; // {constructor: ƒ, ...}
var e = new Object();
var e1 = e.prototype; // undefine

3.原型继承

所有 JavaScript 对象都从原型继承属性和方法。null除外它没有自己的原型对象。日期对象继承自 Date.prototype。数组对象继承自 Array.prototype

Object.prototype 位于原型继承链的顶端:日期对象、数组对象和 Person 对象都继承自 Object.prototype

var Parent = function(name) {
    this.name = name
};
Parent.prototype.sayName = function() {
    return 'sayName'
};
var childA = new Parent('childA');
var childB = new Parent('childB');

console.log(childA.name); // childA
console.log(childB.name); // childB
console.log(childA.sayName()); // sayName
console.log(childB.sayName()); // sayName

上述代码中,如果将sayName放在原型prototype对象上,那么两个实例就会共享同一个方法。对于构造函数来说,prototype是作为构造函数的属性,对于对象实例来说,prototype是对象实例的原型对象,所以prototype既是属性又是对象

原型对象的属性不是对象实例的属性。对象实例的属性是它继承的构造函数定义的属性。因为构造函数内部有一个this关键字来指定将要生成的对象实例。对象实例的属性其实指向的就是构造函数内部定义的属性。只要修改原型对象上的属性和方法,改动立刻体现在所有对象实例上。因为对象实例是共享原型对象的属性和方法的。

对象实例通过new关键字实现继承原型构造器的详解
1.以构造器的prototype属性为原型,创建新对象;
2.将this(也就是新创建的对象)和调用参数传给构造器去执行;
3.如果构造器没有手动返回对象,则返回第一步创建的新对象,如果有,则舍弃掉第一步创建的新对象,返回手动return的对象。

手动实现构造器:

var Parent = function(name) {
    this.name = name;
};
Parent.prototype.sayName = function() {
    console.log(this.name);
};

// 自定义一个new方法
var newMethod = function (Parent, name) {
    /*
    Object.create()方法是ECMAScript 5中新增的方法,这个方法用于创建一个新对象。
    被创建的对象继承另一个对象的原型,在创建新对象时可以指定一些属性。
    语法: Object.create(proto[,propertiesObject]) 
    proto: 对象,要继承的原型 
    propertiesObject: 对象,可选参数,为新创建的对象指定属性对象
     */
    // 1.以构造器的prototype属性为原型,创建新对象,child其实就是this。
    var child = Object.create(Parent.prototype);
    // 2.将this(chhild)和调用参数传给构造器执行。
    var result = Parent.call(child, name);
    // 3.如果构造器没有手动返回对象,则返回第一步的对象。
    return typeof result === 'object' ? result : child;
}

// 创建实例,讲构造函数parent与形参作为参数传入
var childTest = newMethod(Parent, 'child');
childTest.sayName();

构造函数,原型对象与实例之间的关系

4.constructor

每一个原型对象都有一个constructor属性指向关联的构造函数。

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

在这里插入图片描述

5.proto

每一个javaSCript对象除了null,都具有一个属性proto,这个属性是指向该对象的原型。

function Person() {}
var person = new Person();
console.log(person.__proto__ === Person.prototype);
// true

在这里插入图片描述
原型对象的proto指向的是Object的prototype

function Person() {}
console.log(Person.prototype.__proto__ === Object.prototype);
// true

在这里插入图片描述

6.原型链

对象与原型之间的指向链条,我们称为原型链。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值