javascript是基于原型的是什么意思

本文探讨了JavaScript作为面向对象语言,其不同于其他基于类的语言,而是基于原型的特性。在JavaScript中,类仅作为蓝图,而原型是实际的对象实例,对象默认直接从其他对象继承。了解这一点对于深入掌握JavaScript至关重要。

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

When I first started learning JavaScript and OOP I heard over and over that JavaScript is an object-oriented language though it is not based on classes but prototypes. In this article we are going to try to understand what this means and why it is important to know what a prototype is to acknowledge what we are doing.

当我刚开始学习JavaScript和OOP时,我一遍又一遍地听说JavaScript是一种面向对象的语言,尽管它不是基于类而是基于原型。 在本文中,我们将尝试理解这意味着什么,以及为什么重要的是要知道原型是什么,以承认我们在做什么。

In other object-oriented languages when you declare a class you are creating a new complex data type, that is to say, a data type composed of primitive data types. But this is not what happens in JavaScript, even though we use the keyword class since ES2015. While a class is a blueprint, prototypes are object instances. Objects inherit directly from other objects by default in JavaScript.

在其他面向对象的语言中,当您声明一个类时,您正在创建一个新的复杂数据类型,即由原始数据类型组成的数据类型。 但这并不是JavaScript中发生的事情,即使我们从ES2015开始使用关键字class。 虽然类是一个蓝图,但是原型是对象实例。 默认情况下,对象在JavaScript中直接从其他对象继承。

要了解这意味着什么,我们需要了解原型链是什么。 (To understand what this means, we need to understand what the prototype chain is.)

The prototype chain is a tree-shaped structure that connects objects functionality and at the root of this tree is where Object.prototype lays.Object.prototype provides a few methods that show up in all objects, such as toString( ), hasOwnProperty( ) or keys( ).

原型链是连接对象功能树形结构,在此树的根部是Object.prototype所在的位置。 Object.prototype提供了一些在所有对象中显示的方法,例如toString(),hasOwnProperty()或keys()。

Almost every object in JavaScript is an instance of Object if we follow the prototype chain. And as you probably know, almost everything in JavaScript is an object, even some primitive data types (string, boolean and number specifically) can be objects for a tiny fraction of time. So, arrays are objects, functions are objects and, of course, objects are objects.

如果遵循原型链,JavaScript中几乎每个对象都是Object的实例。 您可能知道,JavaScript中的几乎所有内容都是对象,即使某些原始数据类型(特别是字符串,布尔值和数字)也可以在很短的时间内成为对象。 因此,数组是对象,函数是对象,当然,对象是对象。

The prototype chain allows us to create instances of, for example, arrays that have access to all the methods that are available for arrays, like map, forEach, reduce, filter, and a big etc. But arrays also have access to all the Object.prototype functionalities.

原型链使我们可以创建例如数组的实例,这些实例可以访问数组可用的所有方法,例如map,forEach,reduce,filter和big等。但是数组也可以访问所有Object原型功能。

这是怎么发生的? (How does this happen?)

Just to be clear before we continue and because we are using arrays for the example, arrays are syntactic sugar in JavaScript. They are objects with a special behavior to make them look and feel like an array, but under the hood they are something like this:

在继续操作之前要弄清楚,因为我们在示例中使用数组,所以数组是JavaScript中的语法糖。 它们是具有特殊行为的对象,使它们的外观和感觉像数组一样,但是在幕后它们却是这样的:

{
'0': value,
'1': value,
'2': value
}

It turns out that every object has a property called __proto__ which holds a reference to the prototype object of the constructor. So following the array example, an array has access to all the methods in Object.prototype because every array is an instance of the Array object, and the Array object is an instance of the Object object. And this chain goes on until we hit the prototype of Object.prototype which will be null.

事实证明,每个对象都有一个名为__proto__的属性,该属性持有对构造函数原型对象的引用。 因此,在数组示例之后,一个数组可以访问Object.prototype中的所有方法,因为每个数组都是Array对象的实例,而Array对象是Object对象的实例。 这个链条一直持续到我们找到Object.prototype的原型为止,该原型将为null。

Image for post

This way, when we try to execute a method on an object, first JS will lookup in the properties of the object itself. If it doesn’t find a property with that name, it will look in its __proto__ property, which holds a reference to the prototype object of its constructor. If it doesn’t find it there it will look in the __proto__ property of this constructor object. This will go on until it finds it or it doesn’t find it and throws a TypeError.

这样,当我们尝试在对象上执行方法时,首先JS将在对象本身的属性中查找。 如果找不到具有该名称的属性,它将查找其__proto__属性,该属性持有对其构造函数的原型对象的引用。 如果找不到,它将在此构造方法对象的__proto__属性中查找。 这将一直进行到找到它或找不到它并引发TypeError为止。

What this means is that, for example, every time we declare an array we are creating an instance of the Array object that comes with the language. If we look at it in the console we will see that its __proto__ property is linked to the Array object:

这意味着,例如,每次我们声明一个数组时,我们都会创建该语言附带的Array对象的实例。 如果在控制台中查看它,我们将看到其__proto__属性链接到Array对象:

And if we keep looking down the rabbit hole we’ll see that the __proto__ object has a __proto__ property itself that holds a reference to Object.prototype (it’s a reference even though you see all the properties in the console because you know, DRY).

而且,如果我们继续往下看兔子洞,我们会发现__proto__对象本身具有__proto__属性,该属性持有对Object.prototype的引用(即使您在控制台中看到了所有属性,这也是一个引用,因为您知道DRY) 。

Image for post

那么,有没有一种方法可以在没有JavaScript原型的情况下创建对象? (So, is there a way to create an object without a prototype in JavaScript?)

Well, yes there is. One of the ways of creating an object is with Object.create(), to which we can pass as an argument the prototype we want that object to have, which by default is Object.prototype. If we pass it null as an argument we will get an object that is just that, a hash table.

好吧,是的。 创建对象的方法之一是使用Object.create() ,我们可以将该对象具有的原型作为参数传递给该对象,默认情况下为Object.prototype 。 如果将null用作参数,则将得到一个仅是哈希表的对象。

const objectWithoutPrototype = Object.create(null);

My main resources for writing this article were Eloquent JavaScript by Marijn Haverbeke and Will Sentance’s course JavaScript: The Hard Parts of Object Oriented JavaScript.

我写这篇文章的主要资源是Marijn Haverbeke的Eloquent JavaScript和Will Sentance的课程JavaScript:面向对象JavaScript的硬部分

Thanks for reading ❤

感谢您阅读❤

翻译自: https://medium.com/javascript-in-plain-english/what-does-it-mean-that-javascript-is-prototype-based-1974a5e8be49

### Vue2 中原型对象的概念和用法 #### 原型对象的概念 在 JavaScript 和 Vue.js 的开发中,原型对象是一个非常核心的概念。每个构造函数都有一个名为 `prototype` 的属性,它指向一个对象,即原型对象[^1]。对于 Vue 实例来说,其本质上也是一个基于构造函数创建的对象,因此同样遵循 JavaScript原型继承机制。 Vue 实例的原型对象包含了所有可以通过实例访问的方法和属性。这些方法和属性被设计为可以在任何 Vue 组件实例中共享使用。例如,Vue 提供了一些内置方法如 `$set`、`$delete` 等,它们实际上都是定义在 Vue 构造函数的原型上的[^3]。 #### 原型对象的作用 原型对象的主要作用是提供一种机制,使得多个实例能够共享某些属性或方法。这意味着如果你在一个 Vue 应用中有许多组件实例,而这些实例都需要某种通用功能(比如全局状态管理工具 Vuex 或者路由跳转逻辑),你可以通过扩展 Vue 的原型来实现这一点。 具体而言,在 Vue2 中,开发者经常会在项目初始化阶段向 Vue 的原型添加自定义属性或方法。这通常发生在应用入口文件中: ```javascript // 将某个方法挂载到 Vue 的 prototype 上 Vue.prototype.$http = function() { console.log('这是一个 HTTP 请求方法'); }; ``` 这样做的好处在于,之后所有的 Vue 组件实例都能直接通过 `this.$http()` 调用该方法,无需重复声明[^4]。 #### 使用场景举例 假设我们需要在整个应用程序范围内频繁执行 AJAX 请求操作,可以考虑将 Axios 配置并绑定至 Vue 的原型上以便于统一管理和调用: ```javascript import axios from 'axios'; // 添加到 Vue 的原型链中 Vue.prototype.$axios = axios; new Vue({ el: '#app', methods: { fetchData() { this.$axios.get('/api/data') // 这里可以直接使用 $axios 方法 .then(response => { console.log(response.data); }) .catch(error => { console.error(error); }); } }, }); ``` 在这个例子中,我们利用了 Vue 的原型特性简化了跨模块间的依赖注入过程,同时也减少了不必要的冗余代码量。 #### 注意事项 尽管将常用的功能挂载到 Vue 的原型上看似方便快捷,但也需要注意适度原则。过多地修改默认行为可能会导致维护困难以及潜在冲突风险。另外值得注意的是,由于箭头函数没有自身的上下文 (context),所以在涉及需要动态绑定 this 场景时应避免采用箭头函数形式书写回调函数[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值