javascript原型详解

作者: 爆炸的榴莲 | 来源:发表于2016-10-31 17:43 被阅读42次

相信很多人都很困惑于javascript的原型系统,,在我刚开始接触javascript的原型系统的时候,我也非常困惑于它的结构,因为我以前都没有接触过这种基于原型的语言。javascript是一个基于原型的语言,虽然是以函数为第一等公民的语言,但也可以实现面向对象,那就是基于它的原型系统。

javascript原型之函数

现在我们来写一个函数

function A(){

}

这是一个内容为空的函数,但它真的内容为空吗?让我们来看下面一段代码

function A(){

}

console.log(A.toString());;//输出为function A() {}

我们知道,javascript里面的一切都是对象,函数也是,既然函数是对象那么就可以调用函数对象的方法,所以我试着调用了toString 方法,它输出了一个字符串,证明toString方法是存在的。那么toString 方法到底是存在在那里呢,不存在于函数体里,那么存在一个地方必然有toString的函数体且对象function A以某种方式获得了toString方法的调用权。。。

我百度了一下基于原型的语言的特征,基于原型的语言,必然有一个或着多个最初的对象,然后以后的对象都是由这些最初对象克隆过来的,也就是说,基于原型的语言中对象的生成是根据存在的对象来复制的。

好,那我们开始下一步的实验

function A(){

}
console.log(A.__proto__);//Function
console.log(A.prototype);//{}

我输出了Javascript对象所拥有的两个属性,这是javascript语言规定的两个属性_proto_属性指向对象构造函数的原型(不是很理解),prototype属性指向对象的原型。从结果看A函数构造函数的原型是Function,A函数自己的原型是{ }(同样不是很理解)

于是我又做了下面这个实验

Function.prototype.getName = function(){
    return "FunctionTest";
}

function A(){

}
console.log(A.__proto__ === Function.prototype);//true
console.log(A.getName());//FunctionTest

function B(){

}
console.log(B.__proto__ === Function.prototype);//true
console.log(B.getName());//FunctionTest

console.log(A.__proto__ === A.constructor.prototype);//true
//即函数作为对象它的构造函数为Function

我从另外的地方得知javascript里面有内建的Function和Object对象,于是我想着Function对象是否和function A 有些关联呢,当我看到第一条console.log语句返回true的时候,我知道我是正确的,于是我扩展了Function.prototype 给其中添加了getName方法,然后我在用函数A调用了这个方法返回FunctionTest,我又新建了函数B,也调用了这个方法,返回FunctionTest。

至此我知道了函数_proto属性的指向,指向其构造函数的原型,当对象A调用getName函数的时候,由于A对象没有getName函数,javascript会寻找对象A的_proto属性所对应对象,有则调用,没有则继续向上找。

函数的prototype属性我一开始始终没有找到与之对应的对象

console.log(A.prototype === Function.__proto__);//false
console.log(A.prototype === Function.prototype);//false
console.log(A.prototype === Object.__proto__);//false
console.log(A.prototype === Object.prototype);//false

后来我换了一种思考方式终于找到了

console.log(A.prototype.__proto__ === Object.prototype);//true
console.log(A.prototype.prototype);//undefined

而之后我又实验了

console.log(Function.prototype.__proto__ === Object.prototype);

所以最终所有的一切对象的内置函数比如toString都是在Object.prototype里的

然后我又有一个猜测
所有一切函数对象的内置函数比如call,apply都是Function.prototype里的,可以很容易的就验证,普通对象是不能调用call,apply的。

javascript原型之对象

我实验了如下的代码

function A(){
    this.getText = function(){
        return "Text";
    }
}

A.prototype.getName = function(){
    return "my god";
}

var i = new A();

console.log(i.getText());//Text
console.log(i.getName());//my god

然后我改了一下程序

function A(){
    this.getName = function(){
      return "Text";
    }
}

A.prototype.getName = function(){
    return "my god";
}

var i = new A();

console.log(i.getName());//Text
console.log(i.__proto__ === A.prototype);//true
console.log(i.prototype);//undefined

由上面的实验可知,由函数A作为构造函数,所克隆出来的普通对象i的_proto_属性指向函数A的原型(也就是prototype属性),且普通对象i的prototype属性是没有定义的。

当i调用getName函数时,由于i是由函数A克隆出来(大家还没忘记原型语言的特征吧,就是新的对象是由另一个已存在的对象克隆的)的,里面只用getText函数没有getName函数,于是javascript就会寻找i的_proto_属性,而i的proto属性所指向的其实就是A.prototype,所以javascript就在A.prototype里面找getName函数,找到了就调用。所以第二段代码中优先调用返回Text的那个getName函数。

javascript里面还有一种对象就是对象字面量,对象字面量的是否拥有Function.prototype或者Object.prototype的函数呢
请看实验

var a = {
    getName:function(){
        return "a";
    }
}
console.log(a.__proto__);//{}
console.log(a.prototype);//undefined

console.log(a.__proto__ === Object.prototype);//true

由于对象字面量不是由函数对象克隆的,所以没有Function.prototype里面的方法,因为a._proto_指向的是Object.prototype,这就说明javascript只能在a本身和Object.prototype里面找调用的函数。

总结

由上面以一些内容我们可以得出:

1.javascript函数调用顺序是查找对象的原型(即,对象的_proto_属性),一层一层的往上找,直到遇到该函数或者undefined才停止。

2.函数作为特殊的对象,它的原型是Function.prototype,能够调用Function.prototype里面的方法,而Function.prototype的原型又是Object.prototype,故而函数对象既能调用Function.prototype里面的方法,还能调用Object.prototype里面的方法,这就说函数对象即是“函数”又是对象。

3.普通对象的原型是其构造函数的原型(即,A.prototype),而A.prototype的原型是Object.prototype,所以,普通对象只能调用它本身和Object.prototype内的函数

4.对象字面量的原型是Object.prototype。

相关文章

  • 原型和原型链

    原型链分享 原项链详解 什么是原型链: javaScript 常被描述为一种基于原型的语言(prototype-b...

  • JavaScript原型详解

    1,前言 下面是2008年Github创建以来,各种编程语言的排名情况 其中JavaScript自2015年之后就...

  • javascript原型详解

    相信很多人都很困惑于javascript的原型系统,,在我刚开始接触javascript的原型系统的时候,我也非常...

  • JavaScript原型详解

    其实在此之前,关于原型的东西,都是零零散散,没有比较系统地去整理过。 鉴于之前在掘金看到一篇文章,总结得很好,然后...

  • javascript原型详解

    1,前言 早期,js的使用还主要集中于浏览器中,但是随着nodejs进军服务器开发和react native逐渐向...

  • JavaScript原型详解

    1,前言 下面是2008年Github创建以来,各种编程语言的排名情况 其中JavaScript自2013年之后就...

  • Lodash 严重安全漏洞背后 你不得不知道的 JavaScri

    摘要: 详解原型污染。 原文:Lodash 严重安全漏洞背后 你不得不知道的 JavaScript 知识 作者:L...

  • JavaScript原型与原型链终极详解

    JavaScript不包含传统的类继承模型,而是使用prototypal原型模型。 一、原型 刚开始写代码的时...

  • javascript之原型链详解

    对象着手 在谈原型链之前,先了解对象,万物皆对象。 所有引用类型(函数,数组,对象)都拥有proto属性(隐式原型...

  • 原型、原型链

    理解JavaScript原型 彻底理解JavaScript原型 原型 原型是一个对象,所有对象都可以成为原型,其...

网友评论

  • 大狗奇:感谢!用实验得出结论比直接给结论生动很多!

本文标题:javascript原型详解

本文链接:https://www.haomeiwen.com/subject/mxuputtx.html