Js中prototype、[[prototype]]和__proto__的区别和用法

一.显式原型&隐式原型

显式原型:prototype
隐式原型:__proto__

1.1 Important
  • __proto__是每个对象都具有的属性
  • prototypeFunction独有的属性
1.2 Tips
  • 对象的隐式原型的值为其对应构造函数的显式原型的值
    • fn.__proto__ === Function.prototype
  • 函数的prototype属性是定义时自动添加的。默认为{}
  • 对象的__proto__属性是创建对象时自动添加的,默认值为其构造函数的prototype
  • Object.prototype.__proto__ === null
1.3 说了这么多和[[prototype]]有什么关系?

其实[[prototype]]__proto__意义相同,均表示对象的内部属性,其值指向对象原型。前者在一些书籍、规范中表示一个对象的原型属性,后者则是在浏览器实现中指向对象原型。

二.作用

作用方面来讲当然是实现继承了。其中最经典的共享属性方法的原型链继承。其中必不可少的属性就是__protoo__prototype

我们举个栗子

function Son(){}
function Father(){}
Son.prototype = new Father();

如此即实现了继承
我们可以写代码进行验证

Foo.prototype.__proto__ === Bar.prototype  //true

符合上述第三条规则,所以可以通过此方法完成函数的继承。
注意,此为原型链继承,其中的方法鱼属性为此链上的所有实例所共享

三.教你手撸原型链

原型链无非就是一堆继承关系:

  • 我们只需要将儿子原型的__proto__属性指向父亲的prototype属性,构造函数的prototype属性的constructor属性指向其本身即可。
  • 不过需要注意的一点是,已经被实例化的对象__proto__属性指向其构造函数的prototype
  • 另外一个特殊的对象Object。作为所有对象的父类他的原型的__proto__属性指向null

在这里插入图片描述
如此我们就可以看得懂那张经典的原型链图解啦

四.从原理讨论原型链的用处

4.1 typeof

typeof作为《JavaScript高级程序设计》中首推的判断类型方法无疑是大多数人的选择。不过令人烦恼的是我们发现当碰到ArrayFunction等类型时他均返回一个Object。这就有点气人了。所以机智的玩家们采取了Object.prototype.toString.call(obj)方法来识别对象类型。他会返回一个"[object Type]"的东西来告诉你所指对象的类型。

此处就用到了原型链必不可少的prototype。通过改变this指针指向将我们所要验证类型的对象。以完成类型的检验

4.2 instanceof

除去typeof外我们还有另一个方法:instanceof

看过我之前转载的关于typeof与instanceof原理的好兄弟估计会猜到我要说什么,不过我还是要继续BB。

instanceof这个方法用于判断某实例是否从属于某种类型,同时也可以判断一个实例是否是其父类型或者祖先类型的实例。举个栗子

function Son(){}
function Father(){}
Son.prototype = new Father();

var son = new Son();
son instanceof Son  //true
son instanceof Father  //true

看见没,只要你是这一家子的人(实例)那你无论走哪这祖宗祠堂(原型链上的老东西们)都认你。那么他们是如何判断你是不是这家的儿孙呢?当然是原型链。我们来试着写一串伪代码来进行验证

function new_instance_of(leftVaule, rightVaule) { 
    let rightProto = rightVaule.prototype; // 取右表达式的 prototype 值
    leftVaule = leftVaule.__proto__; // 取左表达式的__proto__值
    while (true) {
    	if (leftVaule === null) {
            return false;	
        }
        if (leftVaule === rightProto) {
            return true;	
        } 
        leftVaule = leftVaule.__proto__ 
    }
}

如此这般,通过原型链认祖归宗。咱们看看是否有用

new_instance_of(son, Son)	// true
new_instance_of(son, Father)	// true

今天的内容就这么多
在这里插入图片描述

  • 36
    点赞
  • 96
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
prototype和__proto__都与JavaScript原型链相关。 1. prototype是一个函数特有的属性,它指向一个对象,该对象是使用该函数作为构造函数创建的所有实例的原型。通过原型链,实例可以访问构造函数的原型定义的属性和方法。 例如,我们有一个构造函数Person: ```javascript function Person(name) { this.name = name; } Person.prototype.sayHello = function() { console.log('Hello, ' + this.name + '!'); }; var person1 = new Person('Alice'); person1.sayHello(); // 输出 "Hello, Alice!" ``` 在上面的例子,Person.prototype是一个对象,它包含了我们想要共享给所有Person实例的属性和方法。 2. __proto__是每个对象都有的属性,它指向该对象的原型。通过__proto__,对象可以访问自己的原型定义的属性和方法。 例如,我们再使用上面的Person构造函数创建一个person2对象: ```javascript var person2 = new Person('Bob'); person2.sayHello(); // 输出 "Hello, Bob!" ``` 在上面的例子,person2.__proto__指向Person.prototype,这样person2就可以调用Person.prototype定义的sayHello方法。 虽然__proto__属性在现代JavaScript已经被废弃,但仍然可以在一些老旧的浏览器和环境使用。推荐使用Object.getPrototypeOf()来获取对象的原型,例如: ```javascript var proto = Object.getPrototypeOf(person2); proto === Person.prototype; // true ``` 总结:prototype是构造函数的属性,指向构造函数的原型对象;而__proto__是每个对象都有的属性,指向该对象的原型。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值