精华内容
下载资源
问答
  • 主要介绍了js prototype和__proto__的关系是什么,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 本文实例讲述了JS原型prototype和__proto__用法。分享给大家供大家参考,具体如下: 先来看一个实例 function Foo() { } var foo = new Foo(); console.log(foo.prototype);// undefined console.log(foo.__proto__...
  • JavaScript中的prototype和__proto__

    千次阅读 2018-10-20 23:00:35
    这几天js的学习,不得不说,js真的很诡异,实在太灵活,对于我这个小白来说,...JavaScript中的prototype和__proto__: 首先,先看一段简单的js代码: function Fun() { this.num = 10; }; var fun = new Fun; v...

    这几天js的学习,不得不说,js真的很诡异,实在太灵活,对于我这个小白来说,只能从基础的模仿开始学习了。js来回都脱离不了“键值对”,其中灵活多变的使用,把我搞得是晕头转向。

    JavaScript中的prototype和__proto__:

    首先,先看一段简单的js代码:

    function Fun() {
        this.num = 10;
    };
    var fun = new Fun;
    var func = new Fun;
    console.log("Fun:", Fun);
    console.log("fun:", fun);
    console.log("func:", func);

    我定义了一个Fun(),(js中,一个function,有三个身份:函数,类,对象)。我把Fun()当做一个类,定义了fun和func对象。来看看执行结果吧:

     以上Fun显示有prototype成员,而fun和func对象没有prototype成员。所以,得出结论:只有类(函数)才有prototype成员,这个成员被称为“原型对象”,它指向一个空间,成为“原型空间”。

    以上结果还显示出:fun和func有num成员,但Fun没有。这一点和var fun = new Fun和var fun = new Fun的执行过程有关,过程如下:

    1、申请一个对象实例空间。

    2、将空间首地址赋值给对象fun和func。

    3、执行Fun的构造方法,这个构造方法,就是函数本身。

    4、这个构造方法在执行的时候,是有前缀的(有对象调用此构造方法),这个对象,就是fun和func。

    所以,函数Fun中的this就是fun或func,所以,fun和func显示有num成员。


    console.log("Fun.prototype:", Fun.prototype);

     

     以上代码和结果显示,类的原型本身也是对象(Object),那么,既然是对象,就可以增加成员。


    Fun.prototype.mem = "这是Fun.prototype的一个成员";
    console.log("Fun.prototype:", Fun.prototype);
    console.log("fun.prototype:", fun.prototype);

     

     以上代码和结果显示:给Fun.prototype增加一个成员mem。Fun.prototype显示有mem成员,而fun.prototype显示的是undefined。所以,这个说明对象不存在prototype成员,这是检验对象是否是函数的一种判断方法。(Fun是函数,类,对象;fun和func是对象)。


    console.log("fun.member:", fun.member);
    console.log("func.member:", func.member);
    console.log("fun.__proto__", fun.__proto__);
    console.log("func.__proto__:", func.__proto__);

     

     

     以上代码和结果显示:我们没有给fun和func增加过member成员,所以显示undefined很正常,可以理解。但是,也没有增加过__proto__成员,却显示了出来,而细细比对上面两个执行结果一下,发现:__proto__成员显示的结果和类Fun的prototype成员显示的结果一模一样!!!所以,得出结论:对象存在__proto__这个隐藏成员,这个隐藏成员指向prototype所指向的原型空间。


    func.__proto__.member = 100;
    console.log("Fun.member:", Fun.member);
    console.log("Fun.prototype.member", Fun.prototype.member);

     

     给对象func的__proto__成员成员增加一个成员member,即__proto__指向的prototype原型空间也自然有了member成员。但是,发现:通过类(函数)不能直接访问原型对象的member成员,只能通过prototype访问其原型对象的member成员。


     js中对左值和右值的不同处理过程:

    左值:

    1、左值被看成空间,严格地说,左值也被看成“键”;
    2、对于形如“xxx.成员”的左值,首先在xxx的键值对中查找,若存在,则,用=右侧的表达式的值覆盖其值;
    3、若不存在,则,增加一个成员,再完成赋值。

     如:func.__proto__.member = 100;在func.__proto__的键值对中查找,没有找到member成员,则增加了一个func.__proto__成员,并赋值为100。

    右值:
        1、右值被看成空间,严格地说,右值也被看成“键”;
        2、对于形如“xxx.成员”的右值,首先在xxx的键值对中查找,若存在,则,取出其值,并结束查找;
            若不存在,则,会自动沿着__proto__所指向的原型空间进行查找;
        3、prototype本身也是对象,也应该存在__proto__隐含成员;
        4、第2步的查找,会沿着这个隐含原型链,查找所有“祖先”原型空间中的“右值”;
        5、当遍历了所有原型空间,依然找不到这个“键”(右值),则,其值为undefined。

    func.member = 12;
    var a = fun.member;
    var b = func.member;
    console.log("fun.__proto__:", fun.__proto__);
    console.log("a:",a);
    console.log("b:",b);

     

     例如以上代码和结果:在fun的键值对中查找,不存在member成员,则沿着__proto__所指向的原型空间进行查找,结果显示,

     __proto__所指向的原型空间prototype也没有member,一直沿着这个隐含原型链,遍历了所有原型空间,都没有找到member,所以,a的值为undefined。而对于b,在func的键值对中查找,找到了member成员,则直接取出其值12并赋值。


     

    console.log("Object.__proto__:", Object.__proto__);

     

     

     Object的__proto__成员的显示结果和Function的prototype成员显示一模一样,说明Object的__proto__成员指向Function的原型空间。


    console.log("Function.__proto__:", Function.__proto__);
    console.log("Function.prototype:", Function.prototype);

     

     Function的__proto__成员指向Function的原型空间。


    console.log("Object.prototype.__proto__:", Object.prototype.__proto__);

     

     Object的原型空间prototype的__proto__成员指向null。


    console.log("Function.prototype:", Function.prototype);
    console.log("Object.prototype:", Object.prototype);

     

     

    根据以上结果,发现Function的原型空间prototype的__proto__成员指向Object的原型空间,显示结果相同。

    总结:

    1、在类的构造方法中,用this定义的成员,在该类的生成对象中都可以使用,所以可以等效为java中的public成员(因为在对象的定义阶段,是对象执行了类的构造方法,所以这个this是该对象,自然而然,对象就拥有了构造方法中用this定义的成员)。

    2、在类.prototype中定义的成员,可以等效为java中的public static成员。即该类的所有对象共享同一个副本(因为对象的__proto__成员指向类的prototype原型空间)。

    3、对原型成员的标准访问方法是:类.prototype.成员。

    4、针对上面一系列的分析和验证。对于以下图,自己的一些理解。

    1): 只有类(函数)才有prototype成员,prototype原型空间里有这个类(函数)的构造方法constructor,该类(函数)的构造方法就是其本身,所以,里面又存在prototype成员······

    2):每个对象都有__proto__隐藏成员,指向类(函数)的prototype原型空间。

    3):prototype成员本身也是对象,所以,也有__proto__隐藏成员,指向其基类的原型空间。

    4):Object的__proto__成员指向Function的原型空间,Function的__proto__成员指向Function的原型空间;Object的原型空间prototype的__proto__成员指向null,Function的原型空间prototype的__proto__成员指向Object的原型空间。

    5):类空间的__proto__成员都指向Function的原型空间,原型空间prototype的__proto__成员指向其基类。

    展开全文
  • JS所有对象(包括函数)都是Object的实例,并继承Object.prototype的属性方法; // 普通对象 const obj = {}; console.log(obj instanceof Object); // true // 箭头函数 const myFun = () => {}; console.log...

    首先,明确两点

    1. JS所有对象(包括函数)都是Object的实例,并继承Object.prototype的属性和方法;
    // 普通对象
    const obj = {};
    console.log(obj instanceof Object); // true
    // 箭头函数
    const myFun = () => {};
    console.log(myFun instanceof Object); // true
    // 函数表达式
    const myFun2 = function() {};
    console.log(myFun2 instanceof Object); // true
    
    • Object对象主要的属性和方法举例:
    • constructor属性:保存当前对象的构造函数
    • hasOwnProperty(propertyName)方法:判断该属性是否在当前对象实例中,而不是在对象的原型链中
    • isPrototypeOf(Object)方法:判断当前对象是否在传入的参数对象的原型链上Object.prototype.isPrototypeOf(obj)
    • propertyIsEnumerable(prototypeName)方法:判断给定的属性是否可以被for..in语句给枚举出来(比如constructor属性就不行)
    • toLocaleString()方法
    • toString()方法
    • valueOf()方法
    1. 对象在创建时,会有一些预定义的属性。定义普通对象时,会生成一个__proto__,它指向这个对象的构造函数的prototype。在定义函数时,会生成一个prototype,它同样是一个普通对象,里面包含指向构造函数的constructor以及一个__proto__,这个__proto__同样会指向这个函数的构造函数的prototype(一般为顶层Object,Object.prototype同样有一个__proto__,其值为null

    JS数据类型有:
    基本数据类型:String,Number,Boolean,Null,Undefined,Symbol
    引用数据类型:Object,Array,Function
    Array.prototype是一个数组,arr.__proto__同样是一个数组(其中,arr是Array的实例)

    例如:

    const fn = function(x) {
      this.x = x;
    };
    console.log(fn.prototype.__proto__ === Object.prototype) // true
    console.log(Object.prototype.isPrototypeOf(fn)); // true
    console.log(fn instanceof Object); // true
    // 实例化一个对象
    const obj = new fn("123");
    console.log(obj.__proto__ === fn.prototype) // true
    

    解释下原型链:我们其实可以通过obj.toString()调用该方法,原理其实是,先会在obj这个对象上找有没有toString()方法,没有的话去obj.__proto__也就是fn.prototype上找,而在这个例子里也没有,那就沿着fn.prototype.__proto__向上找,就相当于Object.prototype,如果也没找到那就没有。

    回过头来解释一下,为什么JS所有对象都是Object实例?

    // 定义一个函数并实例化一个对象
    const fun = function() {
      console.log("执行fun函数");
    };
    const obj = new fun();
    
    console.log(obj instanceof fun) //true
    console.log(obj instanceof Object) //true
    console.log(fun instanceof Object) //true
    
    1. 第一个结果分析:obj 是对象,创建时会生成一个__proto__,它指向的是这个对象的构造函数的prototype,即fun函数的prototype(fun是一个函数,定义函数时会生成一个预定义属性prototype) ,执行obj instanceof fun 相当于判断obj.__proto__ === fun.prototype是否正确;
    2. 同样,fun函数的prototype也是一个对象,fun.prototype里面包含构造方法constructor以及__proto__;类似的,由于所有对象都是Object的实例,所以fun.prototype.__proto__指向的是构造函数,即最顶层Object的prototype。而instanceof在多层继承关系中同样有效,也就是说__proto__会一直向下传递,一直找到原型链的尽头。
    3. 而原型链的尽头是Object.prototype.__proto__ === null
    console.log(fun.prototype.__proto__ === Object.prototype) //true
    

    instanceof 用于判断一个变量是否某个对象的实例;
    object instanceof constructor => 检测constructor.prototype是否在object的原型链上;在多层继承关系中,instanceof也同样适用

    最后,我写的其实比较烂,当是学习笔记。推荐阅读我的一个大佬朋友的文章彻底弄懂原型与原型链

    展开全文
  • prototype __proto__笔试题 function Fn() { // 代码字符串 // 谁 new 就是谁的私有属性 this.x = 100; this.y = 200; this.getX = function() { console.log(this.x); }; // 每个函数都有 prototype ...
    function Fn() {
    	// 代码字符串
    	// 谁 new 就是谁的私有属性
    	this.x = 100;
    	this.y = 200;
    	this.getX = function() {
    		console.log(this.x);
    	};
    	// 每个函数都有 prototype 对象
    	// 所以 prototype 是一个堆 Fn.prototype
    	// Fn.prototype 对象也带 __proto__ 属性
    	// 这个对象上有 constructor
    	// constructor 指向函数本身
    };
    
    // 把 getX 挂载到 Fn 的原型对象上
    // 生成一个新的堆内存
    // 属于公共属性
    Fn.prototype.getX = function() {
    	console.log(this.x);
    };
    
    // 把 getY 挂载到 Fn 的原型对象上
    // 生成一个新的堆内存
    // 属于公共属性
    Fn.prototype.getY = function() {
    	console.log(this.y);
    };
    
    // 括号可加可不不加
    // 都是创建类的实例
    // 创建实例对象 f1 / f2 (堆)
    // 同时创建 x: 100 y: 200  getX: function() { ... }
    // 都是这个实例的私有属性
    // 通过 this 创建的变量和对象都属于私有属性
    // 实例都带 __proto__ 属性
    // __proto__ 所属类的原型 prototype
    // 通过原型链往上找都属于 实例(Fn.prototype) 的共有属性
    let f1 = new Fn();
    let f2 = new Fn;
    
     // Object内置类(堆)
    // 有自己的 prototype 原型对象 
    // prototype 指向 Object.prototype 原型对象
    // 有自己的 __proto__ 属性
    // 有自己的 constructor 属性
    // constructor 指向 Object
    // Object.prototype 的 __proto__ 指向的是 null
    
    // 实例指向的堆内存不同,如果自己私有就不会往原型类上查找
    // 因为这个 getX 函数自己私有
    // 所以两个实例的 getX 方法不相等
    console.log(f1.getX === f2.getX); // false
    
    // 因为 getY 这个函数不是自己私有
    // 所以往原型链上查找,结果相等
    // 原因就是他们的 __proto__ 都指向 Fn.prototype 原型对象
    console.log(f1.getY === f2.getY); // true
    
    // 通过原型链查找到的是公共的 getY 
    // 类似于 f1.getY === f2.getY
    console.log(f1.__proto__.getY === Fn.prototype.getY); // true
    
    // f1.__proto__.getX 找的是 Fn.prototype 公共属性
    // f2.getX 因为自己私有
    // 所以不相等
    console.log(f1.__proto__.getX === f2.getX); // false
    
    // f1.getX 属于自己私有的属性
    // Fn.prototype.getX 本身就是公共属性
    // 所以不相等
    console.log(f1.getX === Fn.prototype.getX); // false
    
    // f1 自己身上没有 constructor 
    // 往原型对象上查找
    // 又因为 constructor 指向 函数本身
    // 所以结果就是 Fn 函数
    console.log(f1.constructor); // Fn 函数
    
    // Fn.prototype 的 __proto__ 指向的是 Object.prototy 
    // 因为 Object.prototy 的 constructor 指向 Object 本身
    // 所以是结果 Object
    console.log(Fn.prototype.__proto__.constructor); // ƒ Object() { [native code] }
    
    // f1.getX() 执行
    // 并且 f1.getX 是属于自己私有
    // 所以输出 100
    // 函数执行前面有点
    f1.getX(); // 100
    
    // f1.__proto__.getX(); 
    // 直接查找的是原型对象上的 getX()
    // 原型上的是 console.log(this.x);
    // 因为 f1.__proto__.getX(); getX() 前面有点
    // 所以 相当于 f1.__proto__.x
    // f1.__proto__.x 直接跳过自己(f1 实例对象(堆))往原型对象上查找
    // 此时原型对象上也没有,再往 Object.prototype 对象上查找
    // Object 对象上也没有
    // 最后得到的是 undefined
    f1.__proto__.getX(); // undefined
    
    // 与 f1.getX(); 相同
    f2.getY(); // 200
            
    // Fn.prototype.getY(); 
    // 直接查找的是原型对象上的 getY()
    // 原型上的是 console.log(this.y);
    // 因为 Fn.prototype.getY(); getY() 前面有点
    // 所以 相当于 Fn.prototype.y
    // Fn.prototype.y 直接跳过自己(f2 实例对象(堆))往原型对象上查找
    // 此时原型对象上也没有,再往 Object.prototype 对象上查找
    // Object 对象上也没有
    // 最后得到的是 undefined
    Fn.prototype.getY(); // undefined
    
    展开全文
  • 主要介绍了浅谈javascript中的prototype和__proto__的理解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 每个实例对象都有一个__proto__属性来指向它的构造函数的原型对象,也就是构造函数中的prototype属性 例如 : 每个构造函数本身也是一个实例对象(由内置对象Function()实例化的),那么这个构造函数既有prototype...

    一句话解释:

    每个实例对象都有一个__proto__属性来指向它的构造函数的原型对象,也就是构造函数中的prototype属性

    例如 :

    每个构造函数本身也是一个实例对象(由内置对象Function()实例化的),那么这个构造函数既有prototype属性也有__proto__属性,

    1. 它的__proto__属性指向Function()的prototype,
    2. 用它实例化出的对象的__proto__指向它的prototype属性
    function Func() { }
    
    Func.id = 888;
    Func.getId=function() {
        return this.id;
    }
    Func.prototype.name = 666;
    Func.prototype.getName = function () {
        return this.name;
    }
    var person = new Func();
    
    console.log(person.getName());//能调用
    console.log(person.__proto__);//和Func.prototype等价
    console.log(Func.prototype);
    

    在这里插入图片描述

    另外昨天面试被问到的怎么实现两个对象间的原型链继承

    如果实现两个对象间的原型链继承,比如a和b,a={x:1} b={y:2}, 将a.proto = b, 这样 a 对象就可以点出b对象里面的y属性。 原因是 当你 a点y时,a是没有y属性的,但是它会向着__proto__ 所指向的对象b查找,而b里面有y,于是 a.y = 2

    参考:

    https://juejin.im/post/5ca817ac51882543fc5e3efc

    展开全文
  • JS原型链中的prototype和__proto__的区别

    万次阅读 2018-06-15 09:34:05
    原文 点击打开链接一直认为原型链太过复杂,尤其看过某图后被绕晕了一整子,今天清理硬盘空间(渣电脑)...每个对象都具有一个名为__proto__的属性;2.每个构造函数(构造函数标准为大写开头,如Function(),Objec...
  •   作为一名前端工程师,必须搞懂JS中的prototype、__proto__与constructor属性,相信很多初学者对这些属性存在许多困惑,容易把它们混淆,本文旨在帮助大家理清它们之间的关系并彻底搞懂它们。这里说明一点,__...
  • 我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个对象,它的用途是包含可以由特定类型的所有实例共享的属性方法。(这个对象下面有个...即:对象具有属性__proto__,每个对象都会在其内部初始...
  • 2、原型链:__proto__每个对象都有__proto属性 /*** * 原型:prototype 每个函数都有一个prototype属性 * 原型链:__proto__ 每个对象都有__proto属性 */ function Animal(){ this.type="哺乳类"; } An...
  • JavaScript 理解prototype和__proto__

    千次阅读 2019-07-19 10:51:44
    理解prototype和__proto__ 对象类型 prototype __proto__ 函数对象 Yes Yes 普通对象 No Yes 只有函数对象具有prototype这个属性 prototype和__proto__都是 JS 在定义一个对象时的预定义属性 prototype...
  • prototype 在JS中,每一个函数都有一个prototype属性,它的作用,简单的理解,就是当使用new关键字实例化一个函数的时候,这个函数prototype里面的对象也会共享到新实例里面。 function M1(){ name:'john' } M1....
  • 主要介绍了prototype与__proto__区别详细介绍的相关资料,需要的朋友可以参考下
  • prototype和__proto__

    2020-05-25 20:14:00
    prototype和__proto__ 以前看的时候就对这个prototype和__proto__感到很奇怪。然后今天看了篇文章,又见到了谈论到这个话题的。 然后搜索了一下,发现这些人讲的都好复杂。。。然后就把自己的想法记录一下吧。 原型...
  • 主要介绍了详解帮你彻底搞懂JS中的prototype、__proto__与constructor(图解),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 彻底理解什么是原型链,prototype和__proto__的区别。

    万次阅读 多人点赞 2018-04-19 20:45:12
    1.Javascript中所有的对象都是Object的实例,并继承Object.prototype的属性方法,也就是说,Object.prototype是所有对象的爸爸。(个人感觉搞清楚这一点很重要) ...而定义普通的对象的时候,就会生成一个__proto_...
  • 备忘  function Person() { this.name = 'lishi' ...// Person.prototype.name = 'lishi' Person.prototype.sayName = function () { console.log(this.name) } var person1 = new Person() console.log(Pers...
  • prototype和__proto__是什么以及两者的区别前言prototype的来历new运算符的缺点prototype属性的引入总结 前言 相信很多初学JavaScript的同学我一样,可能听过prototype和__proto__两个属性,但是在实际的项目开发...
  • 每个对象都具有一个名为proto的属性 每个构造函数都具有一个名为prototype的方法(prototype同样带有proto属性) 每个对象的proto属性指向自身构造函数的prototype
  • 一、prototype和__proto__的概念prototype是函数的一个属性(每个函数都有一个prototype属性),这个属性是一个指针,指向一个对象。它是显示修改对象的原型的属性。__proto__是一个对象拥有的内置属性(请注意:...
  • 阐述JS中原型链及prototype和__proto__的区别
  • 原文链接:... 1.Javascript中所有的对象都是Object的实例,并继承Object.prototype的属性方法,也就是说,Object.prototype是所有对象的爸爸。(个人感觉...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 49,925
精华内容 19,970
关键字:

prototype和__proto__