js – 原型链

js – 原型链本文详细介绍了 JavaScript 中的原型链概念 包括构造函数 实例和原型对象的关系 以及原型链的应用 如继承 对象类型的判断

大家好,欢迎来到IT知识分享网。

1. js原型链

原型链由三个部分组成:构造函数、实例、原型对象。

举个例子:

function Person(){ 
   } // 构造函数 var person = new Person() // 实例对象 

我们接触到的js复杂数据类型的构造函数都是function类型,因为复杂数据类型的构造函数都是new Function创建的。
typeof 能检测:
1.基本数据类型(除了null) 、
2.function类型、
3.对象(但是不能区分是什么对象,比如数组和对象分不清)



//函数对象  function Func1(){ 
   }; //函数声明 var Func2 = function(){ 
   }; // 函数表达式(右边是匿名函数) var Func3 = new Function("n1,n2","return n1+n2"); // 函数对象(不推荐) console.log(typeof Func1); //function  console.log(typeof Func2); //function  console.log(typeof Func3); //function  console.log(typeof Object); //function  console.log(typeof Array); //function  console.log(typeof String); //function  console.log(typeof Date); //function  console.log(typeof Function); //function  

A instanceof B 是探讨A的__proto__或是__proto__.proto__或是__proto.proto…是否等于B.prototype,如果是则返回true,否则返回false。

Function instanceof Object //true  Object instanceof Function // true  // Function.__proto__.__proto__ === Object.prototype // Object.__proto__ === Function.prototype 

是不是感觉有些奇怪,因为Object是构造函数,继承了Function.prototype,Function也是对象,继承了Object.prototype。本质原因还是因为Function构造函数的构造函数是他本身,所以Function.__proto__也指向Function.prototype
用原型链图表示:
在这里插入图片描述
还有一个发现,就是原型链的尽头是null,就是说,当实例对象不停的.__proto__尽头是Object.prototype.proto(null)
js内置对象包含Object、Function、Array、String、Boolean、Number、Date、RexExp。



2. js原型链的应用

2.1 js原型链继承

原型链可以用比较小的内存来实现对象共享。只需在原型对象上添加方法(重写原型对象),子实例都可以引用。

function Person() { 
    } // 构造函数 var person = new Person() // 实例对象 Person.prototype.name = 'name'; Person.prototype.get = () => { 
    console.log('get') }; person.get() // 'get' console.log(person.name); // 'name' 

缺点:实例对原型上的引用类型值进行篡改。

Person.prototype.arr = ['a','b']; person.arr.push('c'); console.log(Person.prototype.arr); // ['a','b','c'] 

2.2 利用js原型判断对象类型

typeof A:
只能判断除了null之外的基础数据类型。
复杂数据类型+null都会判断为object,函数会判断为function。

A instanceof B:
表示A是否是B这个构造函数的实例对象,A.proto… === B.prototype则成立。
不能判断基本数据类型。

console.log('111' instanceof String) // false console.log((new String('111')) instanceof String) // true 

A.constructor:
利用原型链和原型,不能判断undefined和null。
利用实例的自动查找原型对象上的constructor属性为构造函数。
‘1’.proto.constructor 为 ƒ String() { [native code] }


console.log('1'.constructor); // ƒ String() { [native code] } console.log((function a(){ 
   }).constructor); // ƒ Function() { [native code] } console.log(null/undefined.constructor); // Uncaught TypeError: Cannot read properties of null (reading 'constructor') 

Object.prototype.toString.call ( A )
可以检测所有数据类型。

console.log(Object.prototype.toString.call(true)) // '[object Boolean]' console.log(Object.prototype.toString.call(undefined)) // '[object Undefined]' console.log(Object.prototype.toString.call(null)) // '[object Null]' console.log(Object.prototype.toString.call(Person)) // 自定义函数'[object Function]' 

2.3 new的过程中发生了什么 / 手写new

new的过程中发生了什么

先看两段代码帮助理解

// 无return function Person1(name, age) { 
    this.name = name; this.age = age; } // 有return  function Person2(name, age) { 
    this.name = name; this.age = age; // 试一试返回基本数据类型和引用数据类型的区别(如return null时候,结果跟Person1一样) return { 
    type: 'dog', owner: 'lihua' } } var func = () => { 
    console.log('my name is lihua') } Person1.prototype.getName = func; Person2.prototype.getName = func; var person1 = new Person1('lihua', 18); var person2 = new Person2('lihua', 18); //{ name: 'lihua', age: 18 } , () => {..} , {getName: ƒ, constructor: ƒ}  console.log(person1, person1.getName, person1.__proto__) //{ type: 'dog', owner: 'lihua' } , undefined , Object.prototype console.log(person2, person2.getName, person2.__proto__) 

所以new的过程中发生了以下四个步骤:

  1. 创建一个空对象
  2. 将空对象的__proto__指向构造函数的prototype
  3. 执行构造函数,改变this指向为创建出来的空对象
  4. 如果构造函数有返回值,对构造函数的返回值做判断,返回值为引用类型时,返回该对象,返回值是基本数据类型时是创建出来的空对象。

手写new

根据以上,手写new如下:

function myNew(constructor, ...args) { 
    var result = constructor(...args) // return 基本数据类型时 if (typeof result !== 'object' || result === null) { 
    let obj = { 
   } //创建空对象 obj.__proto__ = constructor.prototype // 空对象的__proto__指向构造函数的原型 constructor.apply(obj, args) //改变this指向 return obj } // return 引用数据类型时 return result } 

测试一下

function Constructor(a, b) { 
    this.a = a; this.b = b; return a; } Constructor.prototype.getName = () => { 
    return 'hihihi' } var test = myNew(Constructor, 1, 2) console.log(test, test.getName) // Constructor {a: 1, b: 2} () => { return 'hihihi' } 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/110598.html

(0)
上一篇 2026-01-30 15:26
下一篇 2026-01-30 15:45

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信