JavaScript 原型链

本文介绍了JavaScript中创建对象的方法,阐述了原型、构造函数、实例和原型链的概念及关系,解释了instanceof的原理是判断实例对象的__proto__和构造函数的prototype是否引用同一地址,还分析了new运算符的原理并手动实现了该运算符。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:https://www.cnblogs.com/chengzp/p/prototype.html

目录

  1. 创建对象有几种方法
  2. 原型、构造函数、实例、原型链
  3. instanceof的原理
  4. new运算符

 创建对象的方法

  在了解原型链之前,首先先了解一下创建对象的几种方式,介绍以下三种。

<script type="text/javascript">
    // 第一种方式:字面量
    var o1 = {name: 'o1'}
    var o2 = new Object({name: 'o2'})
      // 第二种方式:构造函数
    var M = function (name) { this.name = name; }
    var o3 = new M('o3')
      // 第三种方式:Object.create
    var p = {name: 'p'}
    var o4 = Object.create(p)

  console.log(o1)    
  console.log(o2)
  console.log(o3)
  console.log(o4)
</script>

打印结果:

对象是创建出来了,但你可能对结果很诧异,为什么不同呢?别急,慢慢来。

 原型及原型链

先来一张容易让人懵逼的图

什么是原型对象?实例?构造函数?

概念就不多说了,看代码吧

var M = function (name) { this.name = name; }
var o3 = new M('o3')
  •  实例就是对象,在本例中o3就是实例,M就是构造函数。
  • 实例通过new一个构造函数生成的。
  • 从上图中可以知道,实例的__protpo__指向的是原型对象。
  • 实例的构造函数的prototype也是指向的原型对象。 
  • 原型对象的construor指向的是构造函数。

 

再来通过下面这个图来理解一下 

 

那什么是原型链呢?

  简单理解就是原型组成的链,对象的__proto__它的是原型,而原型也是一个对象,也有__proto__属性,原型的__proto__又是原型的原型,就这样可以一直通过__proto__想上找,这就是原型链,当向上找找到Object的原型的时候,这条原型链就算到头了。

原型对象和实例之间有什么作用呢?

通过一个构造函数创建出来的多个实例,如果都要添加一个方法,给每个实例去添加并不是一个明智的选择。这时就该用上原型了。

在实例的原型上添加一个方法,这个原型的所有实例便都有了这个方法。

接着上面的例子继续演示:

var M = function (name) { this.name = name; }
var o3 = new M('o3')
var o5 = new M()
o3.__proto__.say=furnction(){
   console.log('hello world')
}

o3.say()
o5.say()

打印结果

按照JS引擎的分析方式,在访问一个实例的属性的时候,现在实例本身中找,如果没找到就去它的原型中找,还没找到就再往上找,直到找到。这就是原型链。

补充:

只有函数有prototype,对象是没有的。

但是函数也是有__proto__的,因为函数也是对象。函数的__proto__指向的是Function.prototype。

也就是说普通函数是Function这个构造函数的一个实例。

 

instanceof原理

instanceof是判断实例对象的__proto__和生成该实例的构造函数的prototype是不是引用的同一个地址。

是返回true,否返回false。

注意:实例的instanceof在比较的时候,与原型链上想上找的的构造函数相比都是true。

 继续上面的代码

那怎么判断实例是由哪个构造函数生成的呢?这时候就要用到constructor了。

实例的原型的构造函数, obj.__proto__.constructor

new运算符

new运算符的原理

  • 一个新对象被创建。它继承自foo.prototype。
  • 构造函数返回一个对象。在执行的时候,相应的传参会被传入,同时上下文(this)会被指定为这个新的实例。
  • new foo等同于new foo(), 只能用在不传递任何参数的情况
  • 如果构造函数反悔了一个对象,那个这个对象会取代整个new出来的结果。如果构造函数没有返回对象,那个new出来的结果为步骤1创建的对象。

 下面根据new的工作原理通过代码手动实现一下new运算符

var new2 = function (func) {
    var o = Object.create(func.prototype);    //创建对象
    var k = func.call(o);             //改变this指向,把结果付给k
    if (typeof k === 'object') {         //判断k的类型是不是对象
        return k;                  //是,返回k
    } else {
        return o;                  //不是返回返回构造函数的执行结果
    }
}   

 验证

 

经过上图一系列折腾,不难看出,我们手动编写的new2和new运算符的作用是一样的。

### JavaScript 原型链详解 JavaScript原型链是实现对象继承的一种机制。每个对象在创建时都会关联一个原型对象,并从该原型继承属性和方法。这种原型关系可以形成一条链式结构,称为原型链。 #### 1. 原型链的基本概念 每个 JavaScript 对象都有一个内部属性 `[[Prototype]]`,它指向该对象的原型对象。当尝试访问对象的一个属性或方法时,如果对象本身没有该属性或方法,JavaScript 引擎会沿着原型链向上查找,直到找到该属性或方法,或者到达原型链的末端(即 `null`)[^2]。 #### 2. 原型链的工作机制 以下是一个简单的代码示例来说明原型链的工作原理: ```javascript function Person(name) { this.name = name; } Person.prototype.greet = function() { return `Hello, my name is ${this.name}`; }; const person1 = new Person("Alice"); console.log(person1.greet()); // 输出: Hello, my name is Alice ``` - 在上述代码中,`person1` 是通过 `new Person()` 创建的实例对象。 - `person1` 自身并没有 `greet` 方法,但它的 `[[Prototype]]` 指向了 `Person.prototype`,而 `Person.prototype` 中定义了 `greet` 方法。 - 因此,当调用 `person1.greet()` 时,JavaScript 引擎会在 `person1` 的原型链上找到 `greet` 方法并执行[^3]。 #### 3. 原型链的继承 原型链不仅可以用于单层继承,还可以用于多层继承。例如: ```javascript function Animal() {} Animal.prototype.eat = function() { return "I am eating"; }; function Dog() {} Dog.prototype = Object.create(Animal.prototype); Dog.prototype.bark = function() { return "Woof!"; }; const myDog = new Dog(); console.log(myDog.eat()); // 输出: I am eating console.log(myDog.bark()); // 输出: Woof! ``` - 在这个例子中,`Dog.prototype` 被设置为 `Animal.prototype` 的实例,因此 `Dog` 的实例可以继承 `Animal` 的方法。 - 当调用 `myDog.eat()` 时,JavaScript 引擎会沿着原型链找到 `Animal.prototype.eat` 方法并执行[^1]。 #### 4. 注意事项 - 原型链的末端总是 `null`,因为所有原型链最终都会指向 `Object.prototype`,而 `Object.prototype` 的 `[[Prototype]]` 是 `null`。 - 如果在原型链上修改共享的属性或方法,可能会对所有继承该原型的对象产生影响。因此,在设计继承结构时需要特别小心。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值