JavaScript之原型与原型链【一】

看完此篇文章你将了解到以下内容:

1、什么是函数对象和普通对象,以及两者的关联与异同

2、什么是原型以及原型对象是什么?用原型的目的

3、什么是原型链,以及使用场景
复制代码

一、函数对象和普通对象

在所有的编程语言中,万物皆对象,JavaScript也毫无例外.在JavaScript中分为函数对象和普通对象.Function【函数对象】、Object【普通对象】为JavaScript自带的对象.先从几个例子开始入手,看下浏览器打印的结果是什么:

function foo(){}
    var foo1=function(){}
    var foo2=new Function()
    
    var obj={}
    var obj1=new foo()
    var obj2=new Object()
    
    typeof Function //function
    typeof Object // function
    
    typeof foo //function
    typeof foo1 //function
    typeof foo2 //function
    
    typeof obj // object
    typeof obj1 // object
    typeof obj2 // object
复制代码

从以上例子可以看出,所谓函数对象,都是通过new Function()创建的.反过来说,凡是通new Function()创建的对象都是函数对象.除此之外,就都是普通对象.不难看出,foo,foo1,foo2,Function,Object都是函数对象.obj,obj1,obj2都为普通对象.原型对象就是个普通对象,下面我们来了解下什么是原型对象...

二、原型对象

在JavaScript中,每当定义一个函数对象,对象中都会包含一些预定义的属性,其中函数对象的一个属性就是原型对象【prototype】,看个例子:

function Fn(){}
console.log(Fn.prototype) //Fn{}
console.log(typeof Fn.prototype) //Object
console.log(typeof Function.prototype) // Function 是个特殊的函数,因为Function是被new Function()出来的
console.log(typeof Object.prototype) // Object
console.log(typeof Function.prototype.prototype) //undefined
复制代码

通过上面的例子可以看出:Fn.prototype中的prototype是个隐藏的属性,我们在浏览器打印发现Fn.prototype这个原型对象中包含一个构造函数(constructor)和一个__proto__属性,从console.log(Fn.prototype) //Fn{}可以看出,Fn.prototype为Fn的实例对象.在Fn创建时,创建了它的实例并赋值给它的prototype,过程基本是这样的:

let fn = new Fn();
Fn.protetype =fn;
复制代码

通过上面的过程分析,基本知道为什么Function.prototype是函数对象而不是普通对象了,看下面:

let fn = new Function();
Function.prototype = fn;
复制代码

因为Function.prototype是Function的实例对象,而Function又是函数对象,所以Function.prototype为函数对象.

知道了原型对象是什么,下面来说下原型对象的用处.
原型对象,在JavaScript中主要目的是为了实现继承.【插曲:在Java或C类语言中,面向对象编程是个很好的编程思想,越来越多人从过程编程转向了面向对象编程中,它允许我们把任何事物都可以当做对象去处理,简化了编程的复杂度、代码的易维护性、调测的便利性以及预编译的支持大大降低了程序的响应成本,其中面向对象--封装、继承、多态,就有一项叫继承,因为JavaScript最初就被定义是个弱类型的语言,所以决定它很难像后端语言那样实现复杂的面向对象,但随着前端需求和业务的越来越复杂,急需类似后端面向对象的支持。这时候原型对象出现了,模仿类(class)的实现,以及通过原型链来实现继承】(注:在 ES2015/ES6 中引 入了class关键字,但只是语法糖,JavaScript 仍然是基于原型的[prototype]) 来看个原型对象继承的例子:

function Fruit(type){
    this.type=type;
}
Fruit.prototype.getCategory=function(){
    return this.type;
}
let ty = new Fruit('苹果');
ty.getCategory(); //苹果
console.log('Fruit type==='+ty.getCategory());//Fruit type===苹果
复制代码

从例子中看出,给原型对象Fruit.prototype设置了属性getCategory,在由Fruit实例化出来的普通对象【例:type】属性值就被继承过来了,如何实现继承的,下面就要看下原型链了...

三、原型链

JavaScript中,当创建一个对象时,都会有一个内置的__proto__属性,这个属性指向创建它的函数对象的原型对象prototype,下面看下例子:

function Fruit(type){
    this.type=type;
}
Fruit.prototype.getCategory=function(){
    return this.type;
}
let ty = new Fruit('苹果');
ty.getCategory(); //苹果
console.log('Fruit type==='+ty.getCategory());//Fruit type===苹果

console.log(ty.__proto__===Fruit.prototype);//true
console.log(Fruit.prototype.__proto__===Object.prototype);//true
console.log(Object.prototype.__proto__);//null
复制代码

以上过程梳理一下:

1、普通函数:ty为Fruit的实例化对象,这个ty里有个内部函数属性__proto__这个属性指向创建它的Fruit(函数对象)的原型对象prototype
2、普通对象:Fruit.prototype内也有一个内部属性__proto__指向创建它的Object((函数对象)的原型对象prototype
3、普通对象:Object.prototype内也有一个内部属性__proto__但这个属性比较特殊结果为null;
4、以上过程就是一个原型链,我们把这个以__proto__属性串联起来的直到Object.prototype.__proto__为null时的链,叫原型链
复制代码

如果你有一些关系型数据库基础的话,我们也可以把__proto__当做是外键,prototype为主键,对象和对象之间看做是一张张表,我们把主外键关联起来,就形成了一个链,这样理解起来较容易

下面我们用一张图,来表示这个过程:

JavaScript之浅复制与深复制【二】

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值