js中的原型毫无疑问一个难点,学习如果不深入很容易就晕了!

任何一个js知识点,比如事件流,闭包,继承等,都有许许多多的说法,对于这些知识点我们都应该先熟练的使用,然后自己整理一套属于自己的理解说辞,才不会忘

原型(对象属性)

Javascript规定,每一个函数都有一个prototype对象属性,指向另一个对象(原型链上面的)。

prototype(对象属性)的所有属性和方法,都会被构造函数的实例继承。这意味着,我们可以把那些不变(公用)的属性和方法,直接定义在prototype对象属性上。

prototype就是调用构造函数所创建的那个实例对象的原型(proto)。

prototype可以让所有对象实例共享它所包含的属性和方法。也就是说,不必在构造函数中定义对象信息,而是可以直接将这些信息添加到原型中。

原型链 (JS原型与原型链继承)

实例对象与原型之间的连接,叫做原型链。proto( 隐式连接 )

JS在创建对象的时候,都有一个叫做proto的内置属性,用于指向创建它的函数对象的原型对象prototype。

内部原型(proto)和构造器的原型(prototype)

1、每个对象都有一个proto属性,原型链上的对象正是依靠这个属性连结在一起

2、作为一个对象,当你访问其中的一个属性或方法的时候,如果这个对象中没有这个 方法或属性,那么Javascript引擎将会访问这个对象的proto属性所指向上一个对 象,并在那个对象中查找指定的方法或属性,如果不能找到,那就会继续通过那个对象 的proto属性指向的对象进行向上查找,直到这个链表结束。

实际开发中,有这样一种写法,面向对象,这种写法就是通过构造函数以及原型来运用的(混合模式开发面向对象)

每一个函数都有一个原型属性prototype(对象属性),里面放置的是共有、公有的属性或者方法。(一般情况属性是私有的)。注意,只有函数才有prototyoe属性,

    function Person() {

    }
var p = new Person()
console.log(Person.prototype); // Object{}
console.log(p.prototype); //undefined

这个例子可以发现,函数是存在prototype属性的

任何对象都是默认存在构造器的,此时我们的Person()只是普通函数,它其实是js内置方法Function()构造出来的,而p此时是Person() new出来的,只有new 过了,才叫构造函数

浅谈constructor

在 Javascript 语言中,constructor 属性是专门为 function 而设计的,它存在于每一个 function 的prototype 属性中。这个 constructor 保存了指向 function 的一个引用。

上代码更容易理解

    function Person() {

    }
var p = new Person()
console.log(Person.prototype); // Object{}
console.log(p.prototype); // undifined
console.log(p.constructor); //function Person(){}
此处的p是通过 Person函数构造出来的,所以p的constructor属性指向Person
console.log(Person.constructor); //function Function(){}
之前提过,每个函数其实是通过new Function()构造的
console.log({}.constructor); // function Object(){}
每个对象都是通过new Object()构造的
console.log(Object.constructor); // function Function() {}
Object也是一个函数,它是Function()构造的
console.log([].constructor); //function Array(){}

我想大家此时对于prototype属性有了一定的了解

   console.log(Object.constructor); // function Function() {}

可能大家对于这个有些不理解,毕竟我们实际开发中哪见过这玩意

    console.log(Function instanceof Object); // true
console.log(Object instanceof Function); // true

这样大家是不是就明白了呢 函数是对象构造的 对象也是函数构造的,俩者即是函数也是对象,所以为什么构造函数它是一个函数却返回一个对象,俩者是互相继承的关系

    var o1 = new f1();
typeof o1 //"object"

重点讲解一下原型prototype的用法,最主要的方法就是将属性暴露成公用的,上代码

    function Person(name,age){
this.name = name;
this.age = age;
this.sayHello = function(){
console.log(this.name + "say hello");
}
}
var girl = new Person("bella",23);
var boy = new Person("alex",23);
console.log(girl.name); //bella
console.log(boy.name); //alex
console.log(girl.sayHello === boy.sayHello); //false

再看下面的代码

   function Person(name,age){
this.name = name;
this.age = age; }
Person.prototype.sayHello=function(){
console.log(this.name + "say hello");
}
var girl = new Person("bella",23);
var boy = new Person("alex",23);
console.log(girl.name); //bella
console.log(boy.name); //alex
console.log(girl.sayHello === boy.sayHello); //true

我们给函数Person的原型中声明了sayHello方法,当我们的构造实例对象去访问的时候访问的方法是同一个,这就是prototype原型最大的作用,共享属性和方法

那么prototype与proto有什么关系,先看这么一串代码

    var obj = {}
此处等价于 var obj = new Object()
console.log(obj.__proto__ === Object.prototype)//true

JS 在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做 __proto__ 的内置属性,用于指向创建它的构造函数的原型对象。

根据前面的例子我们很清楚,obj是通过new Object 构造出来的一个对象,那我们Object的原型对象就是Object.prototype,在Object下面构造出来的所有对象,都有一个__proto__ 指向它的原型,我们称这个为原型链

    var obj = []
console.log(obj.__proto__ === Array.prototype)//true

这个也是一样的道理

此处要理解,就是原型对象是谁构造的,是谁构造的我们看构造器

   console.log(Array.prototype.constructor)//Array{}

原型对象肯定是它本身构造的,接着看之前的构造函数代码

   function Person(name,age){
this.name = name;
this.age = age; }
Person.prototype.sayHello=function(){
console.log(this.name + "say hello");
}
var girl = new Person("bella",23);
var boy = new Person("alex",23);
console.log(Person.prototype.constructor); //Person
console.log(girl.__proto__==Person.prototype); //true
console.log(girl.constructor==Person); //true

现在看是不是特别简单 注意这里是两个下划线__proto__ 叫 杠杠proto杠杠

接下来给一串代码

  function Person(){

  }
var person1=new Person()

快速回答

1.person1.__proto__==

2.person1.constructor==

3.Person.__proto__==

4.Person.prototype.constructor==

5.person1.prototype.constructor==

6.Person.prototype==

大家可以测测输入的答案打印是不是为true 如果你很快打出,说明你理解的已经很透彻了

接下来我找几道题一起分析一下,深入了解

              function A(){
    }
    function B(a){
      this.a = a;
    }
    function C(a){       if(a){
        this.a = a;
      }
    }
    A.prototype.a = 1;     B.prototype.a = 1;     C.prototype.a = 1;     console.log(new A().a); //1     console.log(new B().a);//undefined     console.log(new C(2).a);//2

我们先观察第一个

new A() 很明显它是A()构造的实例对象,在下面A函数prototype共享了一个属性a=1,那么实例对象也可以通过这个属性访问到他的值==1

第一个比较简单,我们看第二个

第二个其实是个坑,首先B()函数它声明的时候设置了一个参数,注意里面的方法this,此时this指向的是window,我们都知道,然而在构造函数之后this指向了new B(),然而此时B 没有传入参数,也就是说此时的参数a==undefined,

因此new B()下的属性a==this.a==undefined (不知道这么说能不能理解 ̄□ ̄||)

如果我们给B 传入一个数(可以是a,但a一定要先声明)

                console.log(new B(3).a); //3
    console.log(new B(5).a); //5

这样应该就好理解了,总不能我们自己设置的属性还覆盖不来爸爸给你的属性吧

第三个很好理解,从第二个的角度分析,如果传入参数,输出参数,如果没有 输出1

这道题没什么拐弯,比较简单,我们再看一题

    function Fun(){
var getName = function(){
console.log(1);
}
return this;
}
Fun.getName = function(){
console.log(2);
}
Fun.prototype.getName = function(){
console.log(3);
}
var getName = function(){
console.log(4);
}
function getName(){
console.log(5);
} Fun().getName(); //4
getName(); //4
new Fun().getName();//3
new new Fun().getName();//3

做题一定要一步步来,先看第一个 Fun().getName();

很明显此时是Fun()调用getName(),我们看看Fun(),注意,函数的返回值永远是return,此处return返回了this,在函数中这里的this指向window,也就是说第一步Fun( )返回的是window,转换一下就是window.getName(),

我们在什么找一下全局的getName,最终输出4

第二个其实很简单,我感觉就是来迷惑我们的,前面省略了window,很明显还是4

第三个也太简单了,只要你理解了我上面写的内容,一看就知道输出3

第四个,两个new? 不要慌 我们来分析一下

new后面跟的肯定是函数,用来构造实例对象,所以new Fun()这是不能拆的,

很明显此时new Fun()是一个构造函数,虽然称之为函数,但其实它是一个对象,因为函数是方法,而方法是不能调用属性的,但是对象可以,既然是对象,何来new 构造呢,所以此处分析可以得到new Fun ().getName才是一体连着的,

那很明显就是原型下的方法咯,所以输出3

随着框架应用的越来越广泛,很多用法我们可能并不是那么熟悉,还是希望大家秉着学习之心,多多复习。

转载于:https://www.jianshu.com/p/72156bc03ac1

js原型详解的更多相关文章

  1. 值得收藏的js原型详解

    从虚无到Object 起初,地是空虚混沌,渊面黑暗:这时候一切还是null 神说,要有原型,于是就有了prototype 原型从凭空产生,于是需要一个指向于null的特征,人们把这种特征叫做隐式原型, ...

  2. js对象详解(JavaScript对象深度剖析,深度理解js对象)

    js对象详解(JavaScript对象深度剖析,深度理解js对象) 这算是酝酿很久的一篇文章了. JavaScript作为一个基于对象(没有类的概念)的语言,从入门到精通到放弃一直会被对象这个问题围绕 ...

  3. Node.js npm 详解

    一.npm简介 安装npm请阅读我之前的文章Hello Node中npm安装那一部分,不过只介绍了linux平台,如果是其它平台,有前辈写了更加详细的介绍. npm的全称:Node Package M ...

  4. Vue.js项目详解

    还是以Blog项目来讲解,最近我本人利用闲暇时间,以博客作为参考学习一些新的技术并尝试之前没有尝试过的思路来玩玩. 技术看似枯燥,但是带有一个目的来学,你会发现还是蛮有趣的. 主要实践的就是前后端分离 ...

  5. JS 面向对象详解

    面向对象详解1 OO1.html <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...

  6. 开胃小菜——impress.js代码详解

    README 友情提醒,下面有大量代码,由于网页上代码显示都是同一个颜色,所以推荐大家复制到自己的代码编辑器中看. 今天闲来无事,研究了一番impress.js的源码.由于之前研究过jQuery,看i ...

  7. jquery图片切换插件jquery.cycle.js参数详解

    转自:国人的力量 blog.163.com/xz551@126/blog/static/821257972012101541835491/ 自从使用了jquery.cycle.js,我觉得再也不用自己 ...

  8. 第三天:JS事件详解-事件流

    学习来源: F:\新建文件夹 (2)\HTML5开发\HTML5开发\04.JavaScript基础\6.JavaScript事件详解 学习内容:  1)基础概念 2)举例说明: 代码如上,如果用事件 ...

  9. 【JavaScript】js中的构造函数,和构造函数的实例中的原型详解

    1. 构造函数作为一个对象,他也有他的原型属性,即.prototype:该属性指向的原型对象是Object. 2. 而构造函数产生的实例却没有.prototype属性,但是作为一个对象,该实例却仍然拥 ...

  10. js对象详解

    js自定义对象 一,概述 在Java语言中,我们可以定义自己的类,并根据这些类创建对象来使用,在Javascript中,我们也可以定义自己的类,例如定义User类.Hashtable类等等. 目前在J ...

随机推荐

  1. Linux Shell 字符串截取方法

    Linux 的字符串截取很有用.有八种方法. 假设有变量 var=http://www.aaa.com/123.htm. 1. # 号截取,删除左边字符,保留右边字符. 代码如下: echo ${va ...

  2. 在Windows上使用.NET部署到Docker 《让孩子们走出大坑》

    折腾Docker 有几天了,整别的都没这个糟心.目前已经顺利部署运行起来了.顺便给大家分享下处理在Windows上使用.NET部署到Docker的相关问题解决方法. 1.  Docker无法安装问题 ...

  3. CF590C Three States

    题目链接 题目 见链接. 题解 知识点:BFS. 这道题求连接三个国家的最短路径长度.如果枚举每个点进行bfs,显然不可行,换种思路,从三个国家开始分别进行bfs是可以的. 注意一开始初始化两个距离数 ...

  4. 大白菜方式制作win10 PE启动U盘

    说明 最近帮朋友安装下win10,用了2种制作U盘启动盘的方式.记录一下也方便大家少走弯路. 准备的工具: 1.大白菜软件 2.win10镜像 3.1个U盘,U盘容量 > 8G即可. 制作PE启 ...

  5. OCP试题解析之052-- DROP PROFILE app_user

    133.You created a profile APP_USER and assigned it to the users. After a month, you decide to drop t ...

  6. dilb安装的三种方法

    dilb库安装失败,源码安装嘎嘎报错,所以这里记录一下 dlib库是一个很特殊的库,在下载dlib库之前需要下载两个库(cmake.boost这两个库) pip install cmake boost ...

  7. Taurus.MVC WebMVC 入门开发教程4:数据列表绑定List<Model>

    前言: 在本篇 Taurus.MVC WebMVC 入门开发教程的第四篇文章中, 我们将学习如何实现数据列表的绑定,通过使用 List<Model> 来展示多个数据项. 我们将继续使用 T ...

  8. Avalonia 跨平台框架中如何以正确的姿势使用 OpenGL ES 渲染。

    前言 这是一篇很水的文章,没有任何技术含量,在 Github 已经有很多人对 Avalonia 的 OpenGL ES 支持进行了讨论,但是我还是想写一篇文章来记录一下我是如何在 Avalonia 中 ...

  9. RocketMQ(5) 订阅关系的一致性规范

    多个消费者组订阅了多个Topic,并且每个消费者组里的多个消费者实例的订阅关系应该保持一致. 例如下消费关系, 不同的消费组,消费不同的队列,相同的消费组订阅相同的队列,tag 错误示例: 一个消费者 ...

  10. 21 Educational Codeforces Round 136 (Rated for Div. 2)Knowledge Cards(树状数组、set、+思维、数字华容道)

    最开始猜了个结论错了,猜的是必须要有\(m+n-1\)个方格空着,这样才能保证任意一张牌能从起点到终点. 其实并不是,参考数字华容道,实际上是只要除了终点和起点,以及自身这个方格.我们只需要留出一个空 ...