广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >浅谈JavaScript原型链
  • 486
分享到

浅谈JavaScript原型链

JavaScript原型原型链JavaScript原型链JavaScript原型 2023-05-17 11:05:26 486人浏览 薄情痞子
摘要

目录instanceof 简介Function instanceof Function ?instanceof 运算符的定义javascript 原型继承机制原型与原型链原型继承Ob

instanceof 简介

在 JavaScript 中,判断一个变量的类型通常会用 typeof 运算符,在使用 typeof 运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回 "object"。例如:

var arr = new Array();
console.log( typeof arr ); // object

如果想要确定原型和实例之间的关系就需要用到 instanceof 操作符, 例如:

var arr = new Array();
var Fn = function() {};
var foo = new Fn();
console.log( arr instanceof Array ); // true
console.log( arr instanceof Object ); // true
console.log( foo instanceof Fn); // true
console.log( foo instanceof Function ); // false
console.log( foo instanceof Object ); // true

Function instanceof Function ?

console.log( String instanceof String );
console.log( Function instanceof Function );
console.log( Function instanceof Object );
console.log( Object instanceof Function );
console.log( Object instanceof Object );

要解释这个问题就需要了解 1.JavaScript 语言规范中是如何定义 instanceof 运算符的,2.JavaScript 原型继承机制。

instanceof 运算符的定义

在 ECMAScript-262 中 instanceof 运算符的定义是这样的。

12.9.4 Runtime Semantics: InstanceofOperator(O, C)

The abstract operation InstanceofOperator(O, C) implements the generic alGorithm for determining if an object O inherits from the inheritance path defined by constructor C. This abstract operation perfORMs the following steps:

1. If Type(C) is not Object, throw a TypeError exception.
2. Let instOfHandler be GetMethod(C,@@hasInstance).
3. ReturnIfAbrupt(instOfHandler).
4. If instOfHandler is not undefined, then
a. Return ToBoolean(Call(instOfHandler, C, «O»)).
5. If IsCallable(C) is false, throw a TypeError exception.
6. Return OrdinaryHasInstance(C, O).
NOTE Steps 5 and 6 provide compatibility with previous editions of ECMAScript that did not use a @@hasInstance method to define the instanceof operator semantics. If a function object does not define or inherit @@hasInstance it uses the default instanceof semantics.

7.3.19 OrdinaryHasInstance (C, O)

The abstract operation OrdinaryHasInstance implements the default algorithm for determining if an object O inherits from the instance object inheritance path provided by constructor C. This abstract operation performs the following steps:

1. If IsCallable(C) is false, return false.
2. If C has a [[BoundTargetFunction]] internal slot, then
    a. Let BC be the value of C's [[BoundTargetFunction]] internal slot.
    b. Return InstanceofOperator(O,BC) (see 12.9.4).
3. If Type(O) is not Object, return false.
4. Let P be Get(C, "prototype").
5. ReturnIfAbrupt(P).
6. If Type(P) is not Object, throw a TypeError exception.
7. Repeat
    a. Let O be `O.[[GetPrototypeOf]]()`.
    b. ReturnIfAbrupt(O).
    c. If O is null, return false.
    d. If SameValue(P, O) is true, return true.

官网的定义非常晦涩,上面的翻译成代码大概就是:

function instanceOf( L, R ) { //L 表示左表达式,R 表示右表达式
    var P = R.prototype; // 取 R 的显示原型
    L = L.__proto__; // 取 L 的隐式原型
    while ( true ) { 
        if ( L === null ) return false;
        if ( P === L ) return true; 
        L = L.__proto__; 
    } 
}

再直接点的表达就是 instanceof 会一直在 obj 的原型链上查找,直到找到右边那个构造函数的 prototype 属性,或者为 null 的时候才停止。

类似:

obj.__proto__.__proto__ ... = Obj.prototype

instanceof 会一直沿着隐式原型链 __proto__ 向上查找直到 obj.__proto__.__proto__ ...... === Obj.prototype 为止,如果找到则返回 true,也就是 obj 为 Obj 的一个实例。否则返回 false,obj 不是 Obj 的实例。

JavaScript 原型继承机制

原型与原型链

在 JavaScript 每个函数都有一个 prototype 属性,该属性存储的就是原型对象。JavaScript 构造函数的继承都是通过 prototype 属性, 真正的原型链的实现是通过 __proto__ 实现的,__proto__其实是指向‘父类’的 prototype 属性。例如:

var Foo = function() {}
var foo = new Foo;
console.log(foo.__proto__ === Foo.prototype) // true
console.log(Foo.__proto__ === Function.prototype) // true

原型继承

JavaScript 是单继承的,Object.prototype 是原型链的顶端,所有对象从它继承了包括 valueOf、toString 等等方法和属性。

Object 本身是构造函数,继承了 Function.prototype。 Function 也是对象,继承了 Object.prototype。

Object instanceof Object

ObjectL = Object, ObjectR = Object; 

R = ObjectR.prototype = Object.prototype 
L = ObjectL.__proto__ = Function.prototype 

R != L 
// 循环查找 L 是否还有 __proto__ 
L = Function.prototype.__proto__ = Object.prototype 

R == L 
// 返回 true

String instanceof String

StringL = String, StringR = String;

R = StringR.prototype = String.prototype
L = StringL.__proto__ = Object.prototype

R != L
// 循环查找 L 是否还有 __proto__ 
L = Object.prototype.__proto__ = null
// 返回 false

一切皆对象?

常常说 JavaScript 中一切皆对象,那么就有这样一个问题了:

'string'.__proto__ === String.prototype // true
'string' instanceof String // false

按照上面的推导,'string' instanceof String 应该为 true,但是我们得到的却是 false。 其实问题的关键在于:

console.log(typeof 'string'); // string

'string' 并不是一个 object 对象,MDN 上对 instanceof 的定义是:

The instanceof operator tests whether an object in its prototype chain has the prototype property of a constructor.

 这样又有一个问题了,既然字符串不是对象那为什么有对象才有的属性和方法呢?

var s1 = "string";
var s2 = s1.substring(2);

为了便于操作基本类型值,ECMAScript 还提供了 3 个特殊的引用类型: Boolean、Number 和 String。 实际上,每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们 能够调用一些方法来操作这些数据。

《JavaScript高级程序设计》中是这么解释的:

上面的例子其实当第二行代码访问 s1 时,访问过程处于一种读取模式,也就是要 从内存中读取这个字符串的值。而在读取模式中访问字符串时,后台都会自动完成: (1) 创建 String 类型的一个实例; (2) 在实例上调用指定的方法; (3) 销毁这个实例。

可以将以上三个步骤想象成是执行了下列 ECMAScript 代码。

var s1 = new String("some text");
var s2 = s1.substring(2);
s1 = null;

《Javascript权威指南》里说:

其实(包装对象)在实现上并不一定创建或销毁这个临时对象,然而整个过程看起来是这样的。

这样 Boolean、Number 是一样的逻辑。还剩下两种基本类型:null 和 undefined。

undefined 当我们对变量只声明没有初始化时,输出为 undefined,typeof undefined 返回的是 undefined 也不是 object 类型,所以 undefined 并不是任何对象的实例。

null 表示的是空对象,虽然 typeof null 是 object,但是 null 和 undefined 一样并没有任何属性和方法,在 instanceof 定义中也有判断,如果类型不是 object(这个类型判断并不是跟 typeof 返回值一样),就返回 false。

写在最后

如果这篇文章对你有帮助,请不要吝啬你手中的赞👍!你的鼓励将是我不断分享的动力!😄

到此这篇关于浅谈JavaScript原型链的文章就介绍到这了,更多相关JavaScript原型链内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 浅谈JavaScript原型链

本文链接: https://www.lsjlt.com/news/211074.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 浅谈JavaScript原型链
    目录instanceof 简介Function instanceof Function instanceof 运算符的定义JavaScript 原型继承机制原型与原型链原型继承Obj...
    99+
    2023-05-17
    JavaScript原型 原型链 JavaScript原型链 JavaScript原型
  • 浅谈JS的原型和原型链
    目录1.原型prototype2.原型指针:__proto__总结1.原型prototype javascript中所有函数都具有这个属性,所有具有prototype属性的对象都是一...
    99+
    2022-11-12
  • 浅谈JavaScript工具链不完全指南
    目录概述静态类型检查代码风格检查(Linter)包管理器模块加载器打包工具任务管理工具(Task Runner)转译器构建工具调试工具Node 进程管理器项目脚手架概述 在 Jav...
    99+
    2022-11-12
  • JavaScript 原型与原型链详情
    目录1、prototype(显式原型)2、__proto__(隐式原型)3、constructor(构造函数)4、new的原理5、原型链5.1 原型链的作用5.2 构造函数的__pr...
    99+
    2022-11-12
  • JavaScript原型与原型链是什么
    这篇文章主要介绍“JavaScript原型与原型链是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“JavaScript原型与原型链是什么”文章能帮助大家解决问题...
    99+
    2022-10-19
  • 带你理解JavaScript 原型原型链
    目录一、原型、原型链相等关系理解二:原型、原型链的意思何在 看完这篇文章,你会发现,原型、原型链原来如此简单!  上面经典的原型链相等图,根据下文的学习,你会轻易掌握。 一...
    99+
    2022-11-12
  • 详解JavaScript的原型与原型链
    目录详解原型与原型链构造函数原型对象 访问原型设置原型检测原型prototype、__proto__、constructor之间的关系原型链原型链的作用普通对象与函数对象经...
    99+
    2022-11-13
  • JavaScript原型链详解
    目录1、构造函数和实例2、属性Prototype3、属性__proto__4、访问原型上的方法5、构造函数也有__proto__6、构造函数的原型也有__proto__7、Objec...
    99+
    2022-11-12
  • 浅谈克隆 JavaScript
    目录1、浅克隆2、深克隆1、浅克隆 浅克隆无法copy数组和对象 var obj = { name : "abs", age : '18', sex :...
    99+
    2022-11-12
  • 浅谈Python责任链模式
    目录介绍实现方式案例测试使用场景介绍 责任链模式是一种行为型设计模式,它允许多个对象以链式的形式依次处理请求,直到请求被处理或者无处理对象为止 实现方式 责任链模式由多个处理器组成,...
    99+
    2023-05-16
    Python 责任链模式
  • JavaScript的原型及原型链的用法
    这篇文章给大家介绍JavaScript的原型及原型链的用法,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。JavaScript 是世界上最流行的脚本语言。 JavaScript 是属于 web 的语言,它适用于 PC、笔...
    99+
    2023-06-02
  • Javascript 原型与原型链深入详解
    目录前言对象原型原型链javascript中的类new的实现instanceof的实现javascript的继承总结前言 在前端这块领域,原型与原型链是每一个前端 er 必须掌握的概...
    99+
    2022-11-13
  • JavaScript中原型和原型链是什么
    本篇文章给大家分享的是有关JavaScript中原型和原型链是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。而原型、原型链就是其中之一。每...
    99+
    2022-10-19
  • javascript的原型和原型链是什么
    小编给大家分享一下javascript的原型和原型链是什么,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧! ...
    99+
    2022-10-19
  • 详解JavaScript中的原型和原型链
    目录原型链图原型必备知识prototype属性(显示原型)proto属性(隐式原型)constructor属性总结 原型链图 原型必备知识 要了解原型就必须搞清三个属性:__pro...
    99+
    2022-11-12
  • 深入了解javascript原型和原型链
    目录一、什么是原型二、prototype三、__proto__四、constructor五、实例与原型六、原型的原型七、原型链一、什么是原型 原型:每一个javascript对象(除...
    99+
    2022-11-12
  • JavaScript原型链是什么
    这篇文章主要为大家展示了“JavaScript原型链是什么”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“JavaScript原型链是什么”这篇文章吧。1、构造函数和实例假设你声明一个方法叫做Fo...
    99+
    2023-06-25
  • Javascript的原型和原型链你了解吗
    目录一、为什么要使用原型?怎样去理解原型的出现1、对象字面量创建对象的缺点2、工厂函数3、构造函数二、使用原型三、原型概念辨析四、原型链练习总结一、为什么要使用原型?怎样去理解原型的...
    99+
    2022-11-13
  • 彻底理解JavaScript的原型与原型链
    目录前言基础铺垫prototypecontructor属性__proto__原型链提高总结后语前言 原型与原型链知识历来都是面试中考察的重点,说难不算太难,但要完全理解还是得下一定...
    99+
    2022-11-12
  • JavaScript中的原型和原型链是什么
    这篇文章主要介绍“JavaScript中的原型和原型链是什么”,在日常操作中,相信很多人在JavaScript中的原型和原型链是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JavaScript中的原型和...
    99+
    2023-06-21
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作