乐趣区

关于javascript:js原型详解学习如果不深入很容易晕

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

随着框架利用的越来越宽泛,很多用法咱们可能并不是那么相熟,还是心愿大家秉着学习之心,多多温习

退出移动版