简体   繁体   English

javascript中的原始和引用数据类型

[英]Primitive and Reference data type in javascript

I was getting the pass by reference and primitive data types in javascript through the following example. 我通过以下示例在javascript中通过引用和原始数据类型获取传递。

//This is pass by value example

var firstPerson = "Manish";  
var secondPerson = firstPerson;

firstPerson = "Vikash"; // value of firstPerson changed

console.log(secondPerson); // Manish
console.log(firstPerson); // Vikash



//This is the same as above example

var firstPerson = {name: "Manish"};
var secondPerson = firstPerson;

firstPerson.name = "Vikash";

console.log(secondPerson.name); // Vikash
console.log(firstPerson.name); // Vikash

In the first example, I got that I'm copying the value of firstPerson variable in secondPerson so that it holds the value and prints it. 在第一个例子中,我得到了我在secondPerson中复制firstPerson变量的值,以便它保存值并打印它。 It doesn't care about reassigning any value to the firstPerson variable. 它不关心将任何值重新分配给firstPerson变量。

But what about the second example? 但是第二个例子怎么样?

Why it is printing vikash by executing secondPerson.name even though I've copied the firstPerson = {name: "Manish"} into secondPerson? 为什么它会通过执行secondPerson.name打印vikash ,即使我已将firstPerson = {name: "Manish"}复制到secondPerson中?

This is how I always explained this: 这就是我总是这样解释的:

// 'firstPerson' holds a reference to a string "Manish".
var firstPerson = "Manish";  
// Now you state that 'secondPerson' should hold the reference
// to the same string - "Manish". Since it's a string (a primitive)
// it will be "copied" (depends on implementation), see comments.
var secondPerson = firstPerson;

// Now you say that 'firstPerson' should hold a reference to another
// string, "Vikash".
// That didn't change what the 'secondPerson' refers to, though!
firstPerson = "Vikash";

console.log(secondPerson); // Manish
console.log(firstPerson); // Vikash


// 'firstPerson' holds a reference to an object.
// **Inside** this object, 'name' holds a reference
// to a string "Manish".
var firstPerson = {name: "Manish"};
// 'secondPerson' holds a reference to the same object.
var secondPerson = firstPerson;
// Now you say that the 'name' inside this object should refer
// to another string, "Vikash".
// **That didn't change** what 'firstPerson'
// or 'secondPerson' refers to, though.
firstPerson.name = "Vikash";

console.log(secondPerson.name); // Vikash
console.log(firstPerson.name); // Vikash

You could represent this in this diagram: 您可以在此图表中表示:

// First example
firstPerson    -----> "Manish"
                   |
secondPerson   ----|

// First example after the re-assigment:
firstPerson    -----> "Manish"

secondPerson   -----> "Vikash"

// Second example
firstPerson    -----> { name:    -----> "Manish" }
                   |
secondPerson   ----|

// Second example after re-assignment:
firstPerson    -----> { name:    -----> "Vikash" }
                   |
secondPerson   ----|   <--- this arrow didn't change!

Note how the arrows change after reassignments. 请注意重新分配后箭头如何变化。

In JavaScript Objects are reference types while strings "feel" like reference types somehow (don't forget strings are immutable!). 在JavaScript中,对象是引用类型,而字符串“感觉”类似于引用类型(不要忘记字符串是不可变的!)。 So when you do 所以,当你这样做

var firstPerson = "Manish";  
var secondPerson = firstPerson;

secondPerson has the value "Manish". secondPerson的价值是“Manish”。 When you then do 当你这样做的时候

firstPerson = "Vikash"; 

you are creating a new string and firstPerson will have the new string as its value. 您正在创建一个新字符串,firstPerson将使用新字符串作为其值。 So secondPerson is not changed at all. 所以secondPerson根本没有改变。

I like the following quote from "JavaScript - The Definitive Guide": 我喜欢“JavaScript - The Definitive Guide”中的以下引用

What about strings? 字符串怎么样? A string can have an arbitrary length, so it would seem that strings should be reference types. 字符串可以具有任意长度,因此字符串应该是引用类型。 In fact, though, they are usually considered to be primitive types in JavaScript simply because they are not objects. 实际上,它们通常被认为是JavaScript中的原始类型,因为它们不是对象。 Strings don't actually fit into the primitive versus reference type dichotomy. 字符串实际上并不适合原始与参考类型的二分法。 We'll have more to say about strings and their behavior a little later. 稍后我们会对字符串及其行为有更多的说法。

On the same link you find at 11.2.2. 在同一链接上,您可以在11.2.2找到 Copying and Passing Strings a great description: 复制和传递字符串一个很好的描述:

As mentioned earlier, JavaScript strings don't fit neatly into the primitive type versus reference type dichotomy. 如前所述,JavaScript字符串不能完全适合原始类型与参考类型二分法。 Since strings are not objects, it is natural to assume that they are primitive. 由于字符串不是对象,因此很自然地假设它们是原始的。 If they are primitive types, then by the rules given above, they should be manipulated by value. 如果它们是原始类型,那么根据上面给出的规则,它们应该被值操纵。 But since strings can be arbitrarily long, it would seem inefficient to copy, pass, and compare them byte by byte. 但由于字符串可以任意长,因此逐字节复制,传递和比较它们似乎效率低下。 Therefore, it would also be natural to assume that strings are implemented as reference types. 因此,假设字符串被实现为引用类型也是很自然的。

Instead of making assumptions about strings, suppose we write some JavaScript code to experiment with string manipulation. 假设我们编写了一些JavaScript代码来试验字符串操作,而不是对字符串做出假设。 If strings are copied and passed by reference, we should be able to modify the contents of a string through the reference stored in another variable or passed to a function. 如果通过引用复制和传递字符串,我们应该能够通过存储在另一个变量中的引用或传递给函数来修改字符串的内容。

When we set out to write the code to perform this experiment, however, we run into a major stumbling block: there is no way to modify the contents of a string. 但是,当我们开始编写代码来执行此实验时,我们遇到了一个主要障碍:无法修改字符串的内容。 The charAt( ) method returns the character at a given position in a string, but there is no corresponding setCharAt( ) method. charAt()方法返回字符串中给定位置的字符,但没有相应的setCharAt()方法。 This is not an oversight. 这不是疏忽。 JavaScript strings are intentionally immutable -- that is, there is no JavaScript syntax, method, or property that allows you to change the characters in a string. JavaScript字符串是有意不可变的 - 也就是说,没有允许您更改字符串中的字符的JavaScript语法,方法或属性。

Since strings are immutable, our original question is moot: there is no way to tell if strings are passed by value or by reference. 由于字符串是不可变的,我们原来的问题没有实际意义:没有办法判断字符串是通过值还是通过引用传递的。 We can assume that, for efficiency, JavaScript is implemented so that strings are passed by reference, but in actuality it doesn't matter, since it has no practical bearing on the code we write. 我们可以假设,为了提高效率,JavaScript的实现使得字符串通过引用传递,但实际上并不重要,因为它对我们编写的代码没有实际意义。

In your second example both variables are referencing the same object. 在第二个示例中,两个变量都引用同一个对象。 If you now change this object through any of the two variables you are still changing the same object. 如果现在通过这两个变量中的任何一个更改此对象,则仍在更改同一对象。 Assigning objects is always by reference and never by value!!! 分配对象总是通过引用而永远不是值!

Conclusion: Although strings are often mentioned to be a primitive type they most probably feel or are implemented as a reference type. 结论:尽管字符串经常被提及为基本类型,但它们最有可能感觉或被实现为引用类型。 It's actually like in Java, but in Java Strings are explicitly reference types! 它实际上就像在Java中一样,但在Java Strings中是明确的引用类型!

Assignment makes a copy of the value only if it's a primitive type (like Number, Boolean, etc...). 只有当它是基本类型(如Number,Boolean等)时,赋值才会复制该值。 Otherwise, assignment just copies a reference to the same object (Object, Array, etc...). 否则,赋值只复制对同一对象(对象,数组等)的引用。 A new object is not created with assignment. 未使用赋值创建新对象。

Reference 参考

An assignment does not create a copy/clone/duplicate of an object. 赋值不会创建对象的副本/克隆/副本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM