JavaScript là ngôn ngữ chuyển theo tham chiếu hay chuyển theo giá trị?

1462
Danail Nachev 2009-02-06 11:23.

Các kiểu nguyên thủy (số, chuỗi, v.v.) được truyền theo giá trị, nhưng các đối tượng không xác định, vì chúng có thể được truyền theo giá trị (trong trường hợp chúng ta coi rằng một biến chứa một đối tượng trên thực tế là một tham chiếu đến đối tượng ) và tham chiếu được truyền (khi chúng ta coi rằng biến đối tượng giữ chính đối tượng đó).

Mặc dù nó không thực sự quan trọng vào cuối cùng, tôi muốn biết cách chính xác để trình bày các đối số truyền các quy ước là gì. Có một đoạn trích nào từ đặc tả JavaScript, xác định ngữ nghĩa liên quan đến điều này là gì không?

23 answers

1665
deworde 2010-09-04 07:17.

Nó thú vị trong JavaScript. Hãy xem xét ví dụ này:

function changeStuff(a, b, c)
{
  a = a * 10;
  b.item = "changed";
  c = {item: "changed"};
}

var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};

changeStuff(num, obj1, obj2);

console.log(num);
console.log(obj1.item);
console.log(obj2.item);

Điều này tạo ra đầu ra:

10
changed
unchanged
  • Nếu obj1hoàn toàn không phải là một tham chiếu, thì việc thay đổi obj1.itemsẽ không ảnh hưởng đến obj1bên ngoài của hàm.
  • Nếu đối số là một tham chiếu thích hợp, thì mọi thứ sẽ thay đổi. numsẽ được 100, và obj2.itemsẽ đọc "changed".

Thay vào đó, tình huống là mục được chuyển vào được chuyển theo giá trị. Nhưng mục được truyền theo giá trị tự nó là một tham chiếu. Về mặt kỹ thuật, đây được gọi là chia sẻ theo cuộc gọi .

Trong điều kiện thực tế, điều này có nghĩa là nếu bạn thay đổi chính tham số (như với numobj2), điều đó sẽ không ảnh hưởng đến mục được đưa vào tham số. Nhưng nếu bạn thay đổi NỘI BỘ của tham số, điều đó sẽ truyền ngược lại (như với obj1).

493
Tim Goodman 2011-03-16 06:38.

Nó luôn chuyển theo giá trị, nhưng đối với các đối tượng, giá trị của biến là một tham chiếu. Do đó, khi bạn truyền một đối tượng và thay đổi các thành viên của nó , những thay đổi đó vẫn tồn tại bên ngoài hàm. Điều này làm cho nó trông giống như vượt qua bằng cách tham khảo. Nhưng nếu bạn thực sự thay đổi giá trị của biến đối tượng, bạn sẽ thấy rằng thay đổi không tồn tại, chứng tỏ nó thực sự chuyển qua giá trị.

Thí dụ:

function changeObject(x) {
  x = { member: "bar" };
  console.log("in changeObject: " + x.member);
}

function changeMember(x) {
  x.member = "bar";
  console.log("in changeMember: " + x.member);
}

var x = { member: "foo" };

console.log("before changeObject: " + x.member);
changeObject(x);
console.log("after changeObject: " + x.member); /* change did not persist */

console.log("before changeMember: " + x.member);
changeMember(x);
console.log("after changeMember: " + x.member); /* change persists */

Đầu ra:

before changeObject: foo
in changeObject: bar
after changeObject: foo

before changeMember: foo
in changeMember: bar
after changeMember: bar
156
Shog9 2009-02-06 11:37.

Biến không "giữ" đối tượng; nó chứa một tham chiếu. Bạn có thể gán tham chiếu đó cho một biến khác và bây giờ cả hai đều tham chiếu cùng một đối tượng. Nó luôn được chuyển theo giá trị (ngay cả khi giá trị đó là một tham chiếu ...).

Không có cách nào để thay đổi giá trị được giữ bởi một biến được truyền dưới dạng tham số, điều này có thể thực hiện được nếu JavaScript hỗ trợ truyền bằng tham chiếu.

115
Ray Perea 2014-08-05 01:06.

Hai xu của tôi ... Đây là cách tôi hiểu nó. (Vui lòng sửa cho tôi nếu tôi sai)

Đã đến lúc vứt bỏ mọi thứ bạn biết về giá trị / tham chiếu chuyển qua.

Bởi vì trong JavaScript, không quan trọng là nó được truyền bằng giá trị hay bằng tham chiếu hay bất cứ thứ gì. Điều quan trọng là đột biến so với việc gán các tham số được truyền vào một hàm.

Được rồi, hãy để tôi cố gắng giải thích ý của tôi. Giả sử bạn có một vài đối tượng.

var object1 = {};
var object2 = {};

Những gì chúng tôi đã làm là "gán" ... Chúng tôi đã gán 2 đối tượng trống riêng biệt cho các biến "object1" và "object2".

Bây giờ, hãy nói rằng chúng ta thích object1 hơn ... Vì vậy, chúng ta "gán" một biến mới.

var favoriteObject = object1;

Tiếp theo, vì lý do gì, chúng tôi quyết định rằng chúng tôi thích đối tượng 2 hơn. Vì vậy, chúng tôi làm một nhiệm vụ lại nhỏ.

favoriteObject = object2;

Không có gì xảy ra với object1 hoặc object2. Chúng tôi đã không thay đổi bất kỳ dữ liệu nào cả. Tất cả những gì chúng tôi đã làm là gán lại đối tượng yêu thích của chúng tôi. Điều quan trọng cần biết là object2 và favouriteObject đều được gán cho cùng một đối tượng. Chúng ta có thể thay đổi đối tượng đó thông qua một trong các biến đó.

object2.name = 'Fred';
console.log(favoriteObject.name) // Logs Fred
favoriteObject.name = 'Joe';
console.log(object2.name); // Logs Joe

OK, bây giờ chúng ta hãy xem xét các nguyên thủy như chuỗi chẳng hạn

var string1 = 'Hello world';
var string2 = 'Goodbye world';

Một lần nữa, chúng tôi chọn một yêu thích.

var favoriteString = string1;

Cả hai biến chuỗi yêu thích và string1 của chúng tôi đều được gán cho 'Hello world'. Bây giờ, nếu chúng ta muốn thay đổi Chuỗi yêu thích của mình thì sao ??? Chuyện gì sẽ xảy ra???

favoriteString = 'Hello everyone';
console.log(favoriteString); // Logs 'Hello everyone'
console.log(string1); // Logs 'Hello world'

Uh oh .... Chuyện gì đã xảy ra. Chúng tôi không thể thay đổi string1 bằng cách thay đổi chuỗi yêu thích ... Tại sao ?? Bởi vì chúng tôi đã không thay đổi đối tượng chuỗi của mình . Tất cả những gì chúng tôi đã làm là "RE ASSIGN" biến chuỗi yêu thích thành một chuỗi mới. Về cơ bản, điều này đã ngắt kết nối nó khỏi string1. Trong ví dụ trước, khi chúng ta đổi tên đối tượng của mình, chúng ta không gán bất cứ thứ gì. (Chà, không phải cho chính biến , ... tuy nhiên, chúng tôi đã gán thuộc tính name cho một chuỗi mới.) Thay vào đó, chúng tôi đã biến đổi đối tượng giữ các kết nối giữa 2 biến và các đối tượng bên dưới. (Ngay cả khi chúng ta đã muốn sửa đổi hoặc đột biến đối tượng chuỗi riêng của mình , chúng tôi không thể có, bởi vì chuỗi thực sự bất biến trong JavaScript.)

Bây giờ, chuyển sang hàm và truyền tham số .... Khi bạn gọi một hàm và truyền một tham số, những gì bạn đang làm về cơ bản là "gán" cho một biến mới và nó hoạt động giống hệt như khi bạn chỉ định bằng cách sử dụng dấu (=) bằng.

Lấy các ví dụ này.

var myString = 'hello';

// Assign to a new variable (just like when you pass to a function)
var param1 = myString;
param1 = 'world'; // Re assignment

console.log(myString); // Logs 'hello'
console.log(param1);   // Logs 'world'

Bây giờ, điều tương tự, nhưng với một chức năng

function myFunc(param1) {
    param1 = 'world';

    console.log(param1);   // Logs 'world'
}

var myString = 'hello';
// Calls myFunc and assigns param1 to myString just like param1 = myString
myFunc(myString);

console.log(myString); // logs 'hello'

OK, bây giờ chúng ta hãy đưa ra một vài ví dụ sử dụng các đối tượng thay thế ... trước tiên, không có hàm.

var myObject = {
    firstName: 'Joe',
    lastName: 'Smith'
};

// Assign to a new variable (just like when you pass to a function)
var otherObj = myObject;

// Let's mutate our object
otherObj.firstName = 'Sue'; // I guess Joe decided to be a girl

console.log(myObject.firstName); // Logs 'Sue'
console.log(otherObj.firstName); // Logs 'Sue'

// Now, let's reassign the variable
otherObj = {
    firstName: 'Jack',
    lastName: 'Frost'
};

// Now, otherObj and myObject are assigned to 2 very different objects
// And mutating one object has no influence on the other
console.log(myObject.firstName); // Logs 'Sue'
console.log(otherObj.firstName); // Logs 'Jack';

Bây giờ, điều tương tự, nhưng với một lệnh gọi hàm

function myFunc(otherObj) {

    // Let's mutate our object
    otherObj.firstName = 'Sue';
    console.log(otherObj.firstName); // Logs 'Sue'

    // Now let's re-assign
    otherObj = {
        firstName: 'Jack',
        lastName: 'Frost'
    };
    console.log(otherObj.firstName); // Logs 'Jack'

    // Again, otherObj and myObject are assigned to 2 very different objects
    // And mutating one object doesn't magically mutate the other
}

var myObject = {
    firstName: 'Joe',
    lastName: 'Smith'
};

// Calls myFunc and assigns otherObj to myObject just like otherObj = myObject
myFunc(myObject);

console.log(myObject.firstName); // Logs 'Sue', just like before

Được rồi, nếu bạn đọc hết bài đăng này, có lẽ bây giờ bạn đã hiểu rõ hơn về cách hoạt động của các lệnh gọi hàm trong JavaScript. Không quan trọng là một cái gì đó được chuyển qua tham chiếu hay theo giá trị ... Điều quan trọng là gán và đột biến.

Mỗi khi bạn truyền một biến cho một hàm, bạn đang "Gán" cho bất kỳ tên nào của biến tham số, giống như khi bạn sử dụng dấu bằng (=).

Luôn nhớ rằng dấu bằng (=) có nghĩa là phép gán. Luôn nhớ rằng việc chuyển một tham số cho một hàm trong JavaScript cũng có nghĩa là gán. Chúng giống nhau và 2 biến được kết nối theo cùng một cách (có nghĩa là chúng không giống nhau, trừ khi bạn đếm rằng chúng được gán cho cùng một đối tượng).

Lần duy nhất mà "sửa đổi một biến" ảnh hưởng đến một biến khác là khi đối tượng bên dưới bị đột biến (trong trường hợp đó, bạn chưa sửa đổi biến mà là chính đối tượng.

Không có điểm gì để phân biệt giữa các đối tượng và nguyên thủy, bởi vì nó hoạt động theo cùng một cách chính xác như thể bạn không có một hàm và chỉ sử dụng dấu bằng để gán cho một biến mới.

Lỗi duy nhất là khi tên của biến bạn truyền vào hàm giống với tên của tham số hàm. Khi điều này xảy ra, bạn phải xử lý tham số bên trong hàm như thể nó là một biến hoàn toàn mới riêng tư cho hàm (bởi vì nó là như vậy)

function myFunc(myString) {
    // myString is private and does not affect the outer variable
    myString = 'hello';
}

var myString = 'test';
myString = myString; // Does nothing, myString is still 'test';

myFunc(myString);
console.log(myString); // Logs 'test'
75
geg 2015-09-26 18:06.

Hãy xem xét những điều sau:

  1. Các biến là con trỏ đến các giá trị trong bộ nhớ.
  2. Việc gán lại một biến chỉ đơn thuần trỏ con trỏ đó đến một giá trị mới.
  3. Việc gán lại một biến sẽ không bao giờ ảnh hưởng đến các biến khác đã trỏ vào cùng một đối tượng đó

Vì vậy, hãy quên "chuyển theo tham chiếu / giá trị", đừng bị treo vào "chuyển theo tham chiếu / giá trị" vì:

  1. Các thuật ngữ chỉ được sử dụng để mô tả hành vi của một ngôn ngữ, không nhất thiết phải triển khai cơ bản thực tế. Do sự trừu tượng này, các chi tiết quan trọng cần thiết cho một lời giải thích hợp lý bị mất, điều này chắc chắn dẫn đến tình trạng hiện tại khi một thuật ngữ duy nhất không mô tả đầy đủ hành vi thực tế và thông tin bổ sung phải được cung cấp
  2. Những khái niệm này ban đầu không được định nghĩa với mục đích mô tả javascript nói riêng và vì vậy tôi không cảm thấy bắt buộc phải sử dụng chúng khi chúng chỉ làm tăng thêm sự nhầm lẫn.

Để trả lời câu hỏi của bạn: con trỏ được chuyển.


// code
var obj = {
    name: 'Fred',
    num: 1
};

// illustration
               'Fred'
              /
             /
(obj) ---- {}
             \
              \
               1


// code
obj.name = 'George';


// illustration
                 'Fred'


(obj) ---- {} ----- 'George'
             \
              \
               1


// code
obj = {};

// illustration
                 'Fred'


(obj)      {} ----- 'George'
  |          \
  |           \
 { }            1


// code
var obj = {
    text: 'Hello world!'
};

/* function parameters get their own pointer to 
 * the arguments that are passed in, just like any other variable */
someFunc(obj);


// illustration
(caller scope)        (someFunc scope)
           \             /
            \           /
             \         /
              \       /
               \     /
                 { }
                  |
                  |
                  |
            'Hello world'

Một số nhận xét cuối cùng:

  • Thật hấp dẫn khi nghĩ rằng nguyên thủy được thực thi bởi các quy tắc đặc biệt trong khi các đối tượng thì không, nhưng nguyên thủy chỉ đơn giản là phần cuối của chuỗi con trỏ.
  • Ví dụ cuối cùng, hãy xem xét lý do tại sao nỗ lực thông thường để xóa một mảng không hoạt động như mong đợi.


var a = [1,2];
var b = a;

a = [];
console.log(b); // [1,2]
// doesn't work because `b` is still pointing at the original array
24
user779764 2011-06-03 13:04.

Một đối tượng bên ngoài một hàm được chuyển vào một hàm bằng cách đưa ra một tham chiếu đến đối tượng bên ngoài.

Khi bạn sử dụng tham chiếu đó để thao tác đối tượng của nó, đối tượng bên ngoài sẽ bị ảnh hưởng. Tuy nhiên, nếu bên trong hàm bạn quyết định trỏ tham chiếu đến một thứ khác, bạn hoàn toàn không ảnh hưởng đến đối tượng bên ngoài, bởi vì tất cả những gì bạn làm là chuyển hướng tham chiếu đến một thứ khác.

22
Phil Mander 2015-02-14 01:00.

Hãy nghĩ về nó như thế này: Nó luôn đi theo giá trị. Tuy nhiên, giá trị của một đối tượng không phải là bản thân đối tượng, mà là một tham chiếu đến đối tượng đó.

Đây là một ví dụ, truyền một số (kiểu nguyên thủy)

function changePrimitive(val) {
    // At this point there are two '10's in memory.
    // Changing one won't affect the other
    val = val * 10;
}
var x = 10;
changePrimitive(x);
// x === 10

Lặp lại điều này với một đối tượng sẽ tạo ra các kết quả khác nhau:

function changeObject(obj) {
    // At this point there are two references (x and obj) in memory,
    // but these both point to the same object.
    // changing the object will change the underlying object that
    // x and obj both hold a reference to.
    obj.val = obj.val * 10;
}
var x = { val: 10 };
changeObject(x);
// x === { val: 100 }

Thêm một ví dụ:

function changeObject(obj) {
    // Again there are two references (x and obj) in memory,
    // these both point to the same object.
    // now we create a completely new object and assign it.
    // obj's reference now points to the new object.
    // x's reference doesn't change.
    obj = { val: 100 };
}
var x = { val: 10 };
changeObject(x);
// x === { val: 10}
20
igor 2011-05-13 12:20.

Giải thích rất chi tiết về việc sao chép, chuyển và so sánh theo giá trị và bằng cách tham khảo nằm trong chương này của cuốn sách "JavaScript: Hướng dẫn Định nghĩa" .

Trước khi chúng ta rời khỏi chủ đề về thao tác các đối tượng và mảng bằng tham chiếu, chúng ta cần làm rõ một điểm về danh pháp.

Cụm từ "chuyển qua tham chiếu" có thể có nhiều nghĩa. Đối với một số độc giả, cụm từ đề cập đến một kỹ thuật gọi hàm cho phép một hàm gán giá trị mới cho các đối số của nó và hiển thị các giá trị đã sửa đổi đó bên ngoài hàm. Đây không phải là cách thuật ngữ được sử dụng trong cuốn sách này.

Ở đây, chúng tôi có nghĩa đơn giản là một tham chiếu đến một đối tượng hoặc mảng - không phải bản thân đối tượng - được truyền cho một hàm. Một hàm có thể sử dụng tham chiếu để sửa đổi các thuộc tính của đối tượng hoặc các phần tử của mảng. Nhưng nếu hàm ghi đè tham chiếu bằng tham chiếu đến một đối tượng hoặc mảng mới, thì sửa đổi đó không hiển thị bên ngoài hàm.

Người đọc quen thuộc với nghĩa khác của thuật ngữ này có thể thích nói rằng các đối tượng và mảng được truyền theo giá trị, nhưng giá trị được truyền thực sự là một tham chiếu chứ không phải bản thân đối tượng.

18
Michael Roberts 2009-02-06 11:49.

JavaScript luôn luôn là giá trị truyền ; mọi thứ đều thuộc loại giá trị.

Các đối tượng là các giá trị và các hàm thành viên của các đối tượng chính là các giá trị (hãy nhớ rằng các hàm là các đối tượng hạng nhất trong JavaScript). Ngoài ra, liên quan đến khái niệm rằng mọi thứ trong JavaScript là một đối tượng ; cái này sai. Chuỗi, ký hiệu, số, boolean, null và undefineds là những nguyên thủy .

Đôi khi, họ có thể tận dụng một số chức năng và thuộc tính thành viên được kế thừa từ nguyên mẫu cơ sở của họ, nhưng điều này chỉ để thuận tiện. Nó không có nghĩa là bản thân chúng là đối tượng. Hãy thử những điều sau để tham khảo:

x = "test";
alert(x.foo);
x.foo = 12;
alert(x.foo);

Trong cả hai cảnh báo, bạn sẽ thấy giá trị không được xác định.

13
zangw 2015-12-30 16:20.

Trong JavaScript, loại giá trị chỉ kiểm soát xem giá trị đó sẽ được chỉ định bằng bản sao giá trị hay bản sao tham chiếu .

Giá trị nguyên thủy luôn được gán / truyền bởi value-copy :

  • null
  • undefined
  • chuỗi
  • con số
  • boolean
  • biểu tượng trong ES6

Các giá trị kết hợp luôn được gán / chuyển bởi bản sao tham chiếu

  • các đối tượng
  • mảng
  • chức năng

Ví dụ

var a = 2;
var b = a; // `b` is always a copy of the value in `a`
b++;
a; // 2
b; // 3

var c = [1,2,3];
var d = c; // `d` is a reference to the shared `[1,2,3]` value
d.push( 4 );
c; // [1,2,3,4]
d; // [1,2,3,4]

Trong đoạn mã trên, vì 2là một nguyên thủy vô hướng, agiữ một bản sao ban đầu của giá trị đó và bđược gán một bản sao khác của giá trị. Khi thay đổi b, bạn không có cách nào thay đổi giá trị trong a.

Nhưng cả hai cdđều là các tham chiếu riêng biệt đến cùng một giá trị được chia sẻ [1,2,3], đó là một giá trị ghép. Điều quan trọng cần lưu ý là cả hai đều ckhông d"sở hữu" [1,2,3]giá trị - cả hai đều chỉ là các tham chiếu ngang hàng ngang nhau cho giá trị. Vì vậy, khi sử dụng một trong hai tham chiếu để sửa đổi ( .push(4)) arraychính giá trị được chia sẻ thực tế , nó chỉ ảnh hưởng đến một giá trị được chia sẻ và cả hai tham chiếu sẽ tham chiếu đến giá trị mới được sửa đổi [1,2,3,4].

var a = [1,2,3];
var b = a;
a; // [1,2,3]
b; // [1,2,3]

// later
b = [4,5,6];
a; // [1,2,3]
b; // [4,5,6]

Khi chúng tôi thực hiện nhiệm vụ b = [4,5,6], chúng tôi hoàn toàn không làm gì để ảnh hưởng đến nơi avẫn đang tham chiếu ( [1,2,3]). Để làm điều đó, bsẽ phải là một con trỏ đến athay vì một tham chiếu đến array- nhưng không có khả năng như vậy tồn tại trong JS!

function foo(x) {
    x.push( 4 );
    x; // [1,2,3,4]

    // later
    x = [4,5,6];
    x.push( 7 );
    x; // [4,5,6,7]
}

var a = [1,2,3];

foo( a );

a; // [1,2,3,4]  not  [4,5,6,7]

Khi chúng ta truyền đối số vào a, nó sẽ gán một bản sao của atham chiếu tới x. xalà các tham chiếu riêng biệt trỏ đến cùng một [1,2,3]giá trị. Bây giờ, bên trong hàm, chúng ta có thể sử dụng tham chiếu đó để thay đổi giá trị của chính nó ( push(4)). Nhưng khi chúng tôi thực hiện phép gán x = [4,5,6], điều này không ảnh hưởng đến vị trí mà tham chiếu ban đầu atrỏ đến - vẫn chỉ ở [1,2,3,4]giá trị (hiện đã được sửa đổi) .

Để truyền một cách hiệu quả một giá trị ghép (như một array) bằng bản sao giá trị, bạn cần tạo một bản sao của nó theo cách thủ công, để tham chiếu được truyền vẫn không trỏ đến bản gốc. Ví dụ:

foo( a.slice() );

Giá trị kết hợp (đối tượng, mảng, v.v.) có thể được truyền bằng bản sao tham chiếu

function foo(wrapper) {
    wrapper.a = 42;
}

var obj = {
    a: 2
};

foo( obj );

obj.a; // 42

Ở đây, objhoạt động như một trình bao bọc cho thuộc tính nguyên thủy vô hướng a. Khi được chuyển tới foo(..), một bản sao của objtham chiếu sẽ được chuyển vào và đặt thành wrappertham số. Bây giờ chúng ta có thể sử dụng wrappertham chiếu để truy cập đối tượng được chia sẻ và cập nhật thuộc tính của nó. Sau khi chức năng kết thúc, obj.asẽ thấy giá trị được cập nhật 42.

Nguồn

10
kia nasirzadeh 2019-11-14 14:48.

tốt, đó là về 'hiệu suất' và 'tốc độ' và trong từ đơn giản 'quản lý bộ nhớ' trong ngôn ngữ lập trình.

trong javascript, chúng ta có thể đặt giá trị trong hai lớp: type1 - objectstype2 - tất cả các loại giá trị khác như string& boolean& v.v.

nếu bạn tưởng tượng bộ nhớ như hình vuông bên dưới mà trong mỗi ô vuông chỉ có một giá trị type2 có thể được lưu:

mọi type2-value (xanh lục) là một ô vuông trong khi type1-value (xanh lam) là một nhóm trong số chúng :

vấn đề là nếu bạn muốn chỉ ra một giá trị type2, địa chỉ là đơn giản nhưng nếu bạn muốn làm điều tương tự cho type1-value thì không dễ chút nào! :

và trong một câu chuyện phức tạp hơn:

vì vậy ở đây các tham chiếu có thể giải cứu chúng ta:

trong khi mũi tên màu xanh lá cây ở đây là một biến điển hình, mũi tên màu tím là một biến đối tượng, vì vậy vì mũi tên màu xanh lá cây (biến điển hình) chỉ có một nhiệm vụ (và đó là chỉ ra một giá trị điển hình) nên chúng ta không cần phải tách giá trị của nó khỏi nó để chúng tôi di chuyển mũi tên màu xanh lục với giá trị của nó đến bất cứ đâu và trong tất cả các nhiệm vụ, chức năng, v.v.

nhưng chúng tôi không thể làm điều tương tự với mũi tên màu tím, chúng tôi có thể muốn di chuyển ô 'john' đến đây hoặc nhiều thứ khác ..., vì vậy mũi tên màu tím sẽ dính vào vị trí của nó và chỉ những mũi tên điển hình được chỉ định cho nó sẽ di chuyển ...

một tình huống rất khó hiểu là bạn không thể nhận ra biến được tham chiếu của mình thay đổi như thế nào, hãy xem một ví dụ rất hay:

let arr = [1, 2, 3, 4, 5]; //arr is an object now and a purple arrow is indicating it
let obj2 = arr; // now, obj2 is another purple arrow that is indicating the value of arr obj
let obj3 = ['a', 'b', 'c'];
obj2.push(6); // first pic below - making a new hand for the blue circle to point the 6
//obj2 = [1, 2, 3, 4, 5, 6]
//arr = [1, 2, 3, 4, 5, 6]
//we changed the blue circle object value (type1-value) and due to arr and obj2 are indicating that so both of them changed
obj2 = obj3; //next pic below - changing the direction of obj2 array from blue circle to orange circle so obj2 is no more [1,2,3,4,5,6] and it's no more about changing anything in it but we completely changed its direction and now obj2 is pointing to obj3
//obj2 = ['a', 'b', 'c'];
//obj3 = ['a', 'b', 'c'];

8
Ashish Singh Rawat 2018-09-26 07:31.

Đây là lời giải thích ít hơn về chuyển theo giá trị và chuyển bằng tham chiếu (JavaScript). Trong khái niệm này, họ đang nói về việc truyền biến theo tham chiếu và truyền biến theo tham chiếu.

Truyền theo giá trị (kiểu nguyên thủy)

var a = 3;
var b = a;

console.log(a); // a = 3
console.log(b); // b = 3

a=4;
console.log(a); // a = 4
console.log(b); // b = 3
  • áp dụng cho tất cả kiểu nguyên thủy trong JavaScript (chuỗi, số, Boolean, không xác định và null).
  • a được cấp phát một bộ nhớ (giả sử 0x001) và b tạo một bản sao của giá trị trong bộ nhớ (giả sử 0x002).
  • Vì vậy, việc thay đổi giá trị của một biến không ảnh hưởng đến biến kia, vì cả hai đều nằm ở hai vị trí khác nhau.

Chuyển qua tham chiếu (đối tượng)

var c = { "name" : "john" };
var d = c;

console.log(c); // { "name" : "john" }
console.log(d); // { "name" : "john" }

c.name = "doe";

console.log(c); // { "name" : "doe" }
console.log(d); // { "name" : "doe" }
  • Công cụ JavaScript gán đối tượng cho biến cvà nó trỏ đến một số bộ nhớ, chẳng hạn (0x012).
  • Khi d = c, trong bước này dtrỏ đến cùng một vị trí (0x012).
  • Thay đổi giá trị của mọi thay đổi giá trị cho cả biến.
  • Chức năng là đối tượng

Trường hợp đặc biệt, chuyển theo tham chiếu (đối tượng)

c = {"name" : "jane"};
console.log(c); // { "name" : "jane" }
console.log(d); // { "name" : "doe" }
  • Toán tử bằng (=) thiết lập không gian bộ nhớ hoặc địa chỉ mới
6
Zameer Ansari 2017-08-11 02:43.

chia sẻ những gì tôi biết về các tham chiếu trong JavaScript

Trong JavaScript, khi gán một đối tượng cho một biến, giá trị được gán cho biến là một tham chiếu đến đối tượng:

var a = {
  a: 1,
  b: 2,
  c: 3
};
var b = a;

// b.c is referencing to a.c value
console.log(b.c) // Output: 3
// Changing value of b.c
b.c = 4
// Also changes the value of a.c
console.log(a.c) // Output: 4

4
C Perkins 2016-12-24 08:43.

Ngữ nghĩa học !! Việc thiết lập các định nghĩa cụ thể nhất thiết sẽ khiến một số câu trả lời và nhận xét không tương thích vì chúng không mô tả cùng một thứ ngay cả khi sử dụng cùng một từ và cụm từ, nhưng điều quan trọng là phải vượt qua sự nhầm lẫn (đặc biệt là đối với các lập trình viên mới).

Trước hết, có nhiều cấp độ trừu tượng mà dường như không phải ai cũng nắm được. Các lập trình viên mới hơn đã học về ngôn ngữ thế hệ thứ 4 hoặc thứ 5 có thể gặp khó khăn khi xoay quanh các khái niệm quen thuộc với hợp ngữ hoặc các lập trình viên C không theo từng giai đoạn của con trỏ đến con trỏ đến con trỏ. Truyền tham chiếu không chỉ có nghĩa là khả năng thay đổi đối tượng được tham chiếu bằng cách sử dụng một biến tham số hàm.

Biến : Khái niệm kết hợp của một biểu tượng tham chiếu đến một giá trị tại một vị trí cụ thể trong bộ nhớ. Thuật ngữ này thường quá tải để được sử dụng một mình trong việc thảo luận chi tiết.

Ký hiệu : Chuỗi văn bản được sử dụng để tham chiếu đến biến (tức là tên của biến).

Giá trị : Các bit cụ thể được lưu trữ trong bộ nhớ và được tham chiếu bằng ký hiệu của biến.

Vị trí bộ nhớ : Nơi lưu trữ giá trị của một biến. (Bản thân vị trí được biểu thị bằng một số tách biệt với giá trị được lưu trữ tại vị trí.)

Tham số hàm : Biến được khai báo trong định nghĩa hàm, được sử dụng để tham chiếu đến các biến được truyền vào hàm.

Đối số hàm : Biến bên ngoài hàm được người gọi chuyển đến hàm.

Biến đối tượng : Biến có giá trị cơ bản cơ bản không phải là bản thân "đối tượng", đúng hơn giá trị của nó là một con trỏ (giá trị vị trí bộ nhớ) đến một vị trí khác trong bộ nhớ nơi dữ liệu thực của đối tượng được lưu trữ. Trong hầu hết các ngôn ngữ thế hệ cao hơn, khía cạnh "con trỏ" được ẩn một cách hiệu quả bằng cách tự động hủy tham chiếu trong các ngữ cảnh khác nhau.

Biến nguyên thủy : Biến có giá trị LÀ giá trị thực. Ngay cả khái niệm này cũng có thể phức tạp do tự động đóng gói và các ngữ cảnh giống đối tượng của nhiều ngôn ngữ khác nhau, nhưng ý tưởng chung là giá trị của biến LÀ giá trị thực được biểu thị bằng ký hiệu của biến chứ không phải là một con trỏ đến vị trí bộ nhớ khác.

Đối số và tham số của hàm không giống nhau. Ngoài ra, giá trị của một biến không phải là đối tượng của biến (như nhiều người đã chỉ ra, nhưng dường như bị bỏ qua). Những sự khác biệt này là rất quan trọng để hiểu đúng.

Truyền theo giá trị hoặc Chia sẻ theo lệnh (đối với các đối tượng) : Giá trị của đối số hàm được SAO CHÉP sang một vị trí bộ nhớ khác được tham chiếu bởi ký hiệu tham số của hàm (bất kể nó nằm trên ngăn xếp hay đống). Nói cách khác, tham số hàm đã nhận một bản sao của giá trị của đối số được truyền vào ... VÀ (quan trọng) giá trị của đối số KHÔNG BAO GIỜ ĐƯỢC CẬP NHẬT / THAY ĐỔI bởi hàm gọi. Hãy nhớ rằng, giá trị của một biến đối tượng KHÔNG phải là bản thân đối tượng, đúng hơn nó là con trỏ đến đối tượng, vì vậy việc truyền một biến đối tượng theo giá trị sẽ sao chép con trỏ tới biến tham số hàm. Giá trị của tham số hàm trỏ đến cùng một đối tượng trong bộ nhớ. Bản thân dữ liệu đối tượng có thể được thay đổi trực tiếp thông qua tham số hàm, NHƯNG giá trị của đối số hàm KHÔNG BAO GIỜ ĐƯỢC CẬP NHẬT, vì vậy nó sẽ tiếp tục trỏ đến cùng một đối tượng trong suốt và ngay cả sau khi gọi hàm (ngay cả khi dữ liệu đối tượng của nó bị thay đổi hoặc nếu tham số hàm được gán hoàn toàn cho một đối tượng khác). Không chính xác khi kết luận rằng đối số hàm được truyền bằng tham chiếu chỉ vì đối tượng được tham chiếu có thể cập nhật thông qua biến tham số hàm.

Call / Pass-by-reference : Giá trị của đối số hàm có thể / sẽ được cập nhật trực tiếp bởi tham số hàm tương ứng. Nếu hữu ích, tham số hàm sẽ trở thành một "bí danh" hiệu quả cho đối số - chúng tham chiếu hiệu quả đến cùng một giá trị tại cùng một vị trí bộ nhớ. Nếu một đối số của hàm là một biến đối tượng, thì khả năng thay đổi dữ liệu của đối tượng không khác gì trường hợp truyền giá trị vì tham số hàm sẽ vẫn trỏ đến cùng một đối tượng như đối số. Nhưng trong trường hợp biến đối tượng, nếu tham số hàm được đặt thành một đối tượng hoàn toàn khác, thì đối số cũng sẽ trỏ đến đối tượng khác - điều này không xảy ra trong trường hợp truyền giá trị.

JavaScript không chuyển qua tham chiếu. Nếu bạn đọc kỹ, bạn sẽ nhận ra rằng tất cả các ý kiến ​​trái chiều đều hiểu sai ý nghĩa của giá trị truyền và họ kết luận sai rằng khả năng cập nhật dữ liệu của một đối tượng thông qua tham số hàm đồng nghĩa với "giá trị truyền qua".

Nhân bản / sao chép đối tượng: Một đối tượng mới được tạo ra và dữ liệu của đối tượng gốc được sao chép. Đây có thể là một bản sao sâu hoặc bản sao nông, nhưng vấn đề là một đối tượng mới được tạo ra. Tạo một bản sao của một đối tượng là một khái niệm riêng biệt với giá trị truyền. Một số ngôn ngữ phân biệt giữa đối tượng lớp và các cấu trúc (hoặc tương tự) và có thể có các hành vi khác nhau để truyền các biến thuộc các kiểu khác nhau. Nhưng JavaScript không tự động làm bất cứ điều gì như thế này khi truyền các biến đối tượng. Nhưng sự vắng mặt của tính năng nhân bản đối tượng tự động không chuyển thành tham chiếu truyền.

4
georgeawg 2018-07-26 05:47.

JavaScript chuyển các kiểu nguyên thủy theo giá trị và các kiểu đối tượng bằng tham chiếu

Bây giờ, mọi người thích tranh cãi không ngừng về việc liệu "chuyển qua tham chiếu" có phải là cách chính xác để mô tả những gì Java et al hay không. thực sự làm. Vấn đề là đây:

  1. Truyền một đối tượng không sao chép đối tượng.
  2. Một đối tượng được truyền cho một hàm có thể có các thành viên của nó được hàm sửa đổi.
  3. Hàm không thể sửa đổi giá trị nguyên thủy được truyền cho một hàm. Một bản sao được tạo ra.

Trong cuốn sách của tôi, nó được gọi là tham khảo.

- Brian Bi - Những ngôn ngữ lập trình nào được chuyển qua tham chiếu?


Cập nhật

Đây là một phản bác cho điều này:

Không có "chuyển qua tham chiếu" có sẵn trong JavaScript.

3
dpp 2014-09-16 23:19.

Cách đơn giản của tôi để hiểu điều này ...

  • Khi gọi một hàm, bạn đang truyền nội dung (tham chiếu hoặc giá trị) của các biến đối số, chứ không phải chính các biến đó.

    var var1 = 13;
    var var2 = { prop: 2 };
    
    //13 and var2's content (reference) are being passed here
    foo(var1, var2); 
    
  • Bên trong hàm, các biến tham số inVar1inVar2, nhận nội dung được truyền vào.

    function foo(inVar1, inVar2){
        //changing contents of inVar1 and inVar2 won't affect variables outside
        inVar1 = 20;
        inVar2 = { prop: 7 };
    }
    
  • Kể từ khi inVar2nhận được tham chiếu của { prop: 2 }, bạn có thể thay đổi giá trị thuộc tính của đối tượng.

    function foo(inVar1, inVar2){
        inVar2.prop = 7; 
    }
    
3
John Sonderson 2014-11-02 02:43.

Truyền đối số cho một hàm trong JavaScript tương tự như truyền tham số theo giá trị con trỏ trong C:

/*
The following C program demonstrates how arguments
to JavaScript functions are passed in a way analogous
to pass-by-pointer-value in C. The original JavaScript
test case by @Shog9 follows with the translation of
the code into C. This should make things clear to
those transitioning from C to JavaScript.

function changeStuff(num, obj1, obj2)
{
    num = num * 10;
    obj1.item = "changed";
    obj2 = {item: "changed"};
}

var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};
changeStuff(num, obj1, obj2);
console.log(num);
console.log(obj1.item);    
console.log(obj2.item);

This produces the output:

10
changed
unchanged
*/

#include <stdio.h>
#include <stdlib.h>

struct obj {
    char *item;
};

void changeStuff(int *num, struct obj *obj1, struct obj *obj2)
{
    // make pointer point to a new memory location
    // holding the new integer value
    int *old_num = num;
    num = malloc(sizeof(int));
    *num = *old_num * 10;
    // make property of structure pointed to by pointer
    // point to the new value
    obj1->item = "changed";
    // make pointer point to a new memory location
    // holding the new structure value
    obj2 = malloc(sizeof(struct obj));
    obj2->item = "changed";
    free(num); // end of scope
    free(obj2); // end of scope
}

int num = 10;
struct obj obj1 = { "unchanged" };
struct obj obj2 = { "unchanged" };

int main()
{
    // pass pointers by value: the pointers
    // will be copied into the argument list
    // of the called function and the copied
    // pointers will point to the same values
    // as the original pointers
    changeStuff(&num, &obj1, &obj2);
    printf("%d\n", num);
    puts(obj1.item);
    puts(obj2.item);
    return 0;
}
3
DannyNiu 2017-07-29 03:17.

Đối với các luật sư ngôn ngữ lập trình, tôi đã xem qua các phần sau của ECMAScript 5.1 (dễ đọc hơn phiên bản mới nhất) và đi xa hơn khi hỏi nó trong danh sách gửi thư ECMAScript.

TL; DR : Mọi thứ đều được truyền theo giá trị, nhưng các thuộc tính của Đối tượng là tham chiếu và định nghĩa của Đối tượng thiếu tiêu chuẩn một cách đáng sợ.

Xây dựng danh sách đối số

Phần 11.2.4 "Danh sách đối số" nói như sau về cách tạo danh sách đối số chỉ bao gồm 1 đối số:

ArgumentList sản xuất: AssignmentExpression được đánh giá như sau:

  1. Gọi ref là kết quả đánh giá AssignmentExpression.
  2. Giả sử là GetValue (ref).
  3. Trả về một Danh sách có mục duy nhất là đối số.

Phần này cũng liệt kê các trường hợp mà danh sách đối số có 0 hoặc> 1 đối số.

Vì vậy, mọi thứ được thông qua bằng cách tham chiếu.

Quyền truy cập thuộc tính đối tượng

Phần 11.2.1 "Người tiếp cận tài sản"

Thành viên sản xuất: MemberExpression [Biểu thức] được đánh giá như sau:

  1. Đặt baseReference là kết quả đánh giá MemberExpression.
  2. Đặt baseValue là GetValue (baseReference).
  3. Đặt propertyNameReference là kết quả của việc đánh giá Biểu thức.
  4. Đặt propertyNameValue là GetValue (propertyNameReference).
  5. Gọi CheckObjectCoercible (baseValue).
  6. Đặt propertyNameString là ToString (propertyNameValue).
  7. Nếu sản xuất cú pháp đang được đánh giá được chứa trong mã chế độ nghiêm ngặt, hãy đặt nghiêm ngặt là đúng, nếu không, nghiêm ngặt là sai.
  8. Trả về giá trị của kiểu Tham chiếu có giá trị cơ sở là baseValue và có tên được tham chiếu là propertyNameString và có cờ chế độ nghiêm ngặt là nghiêm ngặt.

Do đó, các thuộc tính của Đối tượng luôn có sẵn dưới dạng tham chiếu.

Tham khảo

Nó được mô tả trong phần 8.7 "Kiểu đặc tả tham chiếu", rằng các tham chiếu không phải là kiểu thực trong ngôn ngữ - chúng chỉ được sử dụng để mô tả hành vi của phép xóa, kiểu và các toán tử gán.

Định nghĩa "Đối tượng"

Nó được định nghĩa trong ấn bản 5.1 rằng "Một đối tượng là một tập hợp các thuộc tính". Do đó, chúng ta có thể suy luận rằng giá trị của đối tượng là bộ sưu tập, nhưng giá trị của bộ sưu tập là gì thì không được xác định rõ trong thông số kỹ thuật và cần một chút nỗ lực để hiểu.

3
miguelr 2019-04-20 20:06.

Tài liệu MDN giải thích rõ ràng, không quá dài dòng:

Các tham số của một lời gọi hàm là các đối số của hàm . Các đối số được chuyển cho các hàm theo giá trị . Nếu hàm thay đổi giá trị của một đối số, thay đổi này không được phản ánh trên toàn cục hoặc trong hàm đang gọi. Tuy nhiên, các tham chiếu đối tượng cũng là các giá trị và chúng đặc biệt: nếu hàm thay đổi thuộc tính của đối tượng được giới thiệu, thì thay đổi đó sẽ hiển thị bên ngoài hàm, (...)

Nguồn: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions#Description

2
Jonas Wilms 2020-07-27 05:32.

quan sát: Nếu người quan sát không có cách nào để kiểm tra bộ nhớ cơ bản của động cơ, thì không có cách nào để xác định ướt hơn một giá trị bất biến được sao chép hoặc một tham chiếu được chuyển qua.

JavaScript ít nhiều bất khả tri đối với mô hình bộ nhớ cơ bản. Không có cái gọi là tham chiếu ². JavaScript có các giá trị . Hai biến có thể giữ cùng một giá trị (hoặc chính xác hơn: hai bản ghi môi trường có thể ràng buộc cùng một giá trị). Loại giá trị duy nhất có thể thay đổi là các đối tượng thông qua các phép toán [[Lấy]] và [[Đặt]] trừu tượng của chúng. Nếu bạn quên máy tính và bộ nhớ, đây là tất cả những gì bạn cần để mô tả hành vi của JavaScripts và nó cho phép bạn hiểu đặc điểm kỹ thuật.

 let a = { prop: 1 };
 let b = a; // a and b hold the same value
 a.prop = "test"; // the object gets mutated, can be observed through both a and b
 b = { prop: 2 }; // b holds now a different value
 

Bây giờ bạn có thể tự hỏi mình làm thế nào hai biến có thể giữ cùng một giá trị trên máy tính. Sau đó, bạn có thể xem xét mã nguồn của một công cụ JavaScript và rất có thể bạn sẽ tìm thấy thứ gì đó mà một lập trình viên của ngôn ngữ mà công cụ được viết sẽ gọi là tham chiếu.

Vì vậy, trên thực tế, bạn có thể nói rằng JavaScript là "chuyển theo giá trị", trong khi giá trị có thể được chia sẻ, bạn có thể nói rằng JavaScript là "chuyển theo tham chiếu", có thể là một trừu tượng logic hữu ích cho các lập trình viên từ các ngôn ngữ cấp thấp, hoặc bạn có thể gọi hành vi là "gọi bằng cách chia sẻ". Vì không có cái gọi là tham chiếu trong JavaScript, tất cả những điều này không sai cũng không đúng. Vì vậy, tôi không nghĩ rằng câu trả lời đặc biệt hữu ích để tìm kiếm.

² Thuật ngữ Tham chiếu trong đặc tả không phải là một tham chiếu theo nghĩa truyền thống. Nó là một vùng chứa cho một đối tượng và tên của một thuộc tính và là một giá trị trung gian (ví dụ: a.bđánh giá thành Reference { value = a, name = "b" }). Thuật ngữ tham chiếu đôi khi cũng xuất hiện trong đặc tả ở các phần không liên quan.

1
lid 2014-05-17 15:01.

Lời giải thích ngắn gọn nhất mà tôi tìm thấy là trong hướng dẫn kiểu AirBNB :

  • Nguyên thủy : Khi bạn truy cập một kiểu nguyên thủy, bạn làm việc trực tiếp trên giá trị của nó

    • chuỗi
    • con số
    • boolean
    • vô giá trị
    • chưa xác định

Ví dụ:

var foo = 1,
    bar = foo;

bar = 9;

console.log(foo, bar); // => 1, 9
  • Phức tạp : Khi bạn truy cập một kiểu phức tạp, bạn làm việc trên một tham chiếu đến giá trị của nó

    • vật
    • mảng
    • chức năng

Ví dụ:

var foo = [1, 2],
    bar = foo;

bar[0] = 9;

console.log(foo[0], bar[0]); // => 9, 9

Tức là các kiểu nguyên thủy hiệu quả được truyền theo giá trị và các kiểu phức tạp được truyền bằng tham chiếu.

1
steviejay 2016-10-30 04:50.

Tôi đã đọc qua những câu trả lời này nhiều lần, nhưng không THỰC SỰ hiểu được nó cho đến khi tôi tìm hiểu về định nghĩa kỹ thuật của "Gọi bằng cách chia sẻ" theo thuật ngữ của Barbara Liskov

Ngữ nghĩa của lệnh gọi bằng cách chia sẻ khác với lệnh gọi bằng cách tham chiếu ở chỗ các phép gán cho các đối số của hàm trong hàm không hiển thị cho người gọi (không giống như theo ngữ nghĩa tham chiếu) [cần trích dẫn], vì vậy, ví dụ: nếu một biến đã được chuyển, thì không thể để mô phỏng một phép gán trên biến đó trong phạm vi của người gọi. Tuy nhiên, vì hàm có quyền truy cập vào cùng một đối tượng như người gọi (không có bản sao nào được thực hiện), các đột biến đối với các đối tượng đó, nếu các đối tượng có thể thay đổi, trong hàm sẽ hiển thị với người gọi, có thể khác với lệnh gọi theo giá trị ngữ nghĩa. Các đột biến của một đối tượng có thể thay đổi trong hàm được hiển thị cho người gọi vì đối tượng không được sao chép hoặc nhân bản - nó được chia sẻ.

Nghĩa là, các tham chiếu tham số có thể thay đổi nếu bạn truy cập và truy cập vào chính giá trị tham số. Mặt khác, việc gán cho một tham số sẽ biến mất sau khi đánh giá và người gọi hàm không thể truy cập được.

1
Narayon 2016-10-20 02:07.

Trong ngôn ngữ cấp thấp, nếu bạn muốn chuyển một biến bằng tham chiếu, bạn phải sử dụng một cú pháp cụ thể trong việc tạo hàm:

int myAge = 14;
increaseAgeByRef(myAge);
function increaseAgeByRef(int &age) {
  *age = *age + 1;
}

Đây &agelà một tham chiếu đến myAge, nhưng nếu bạn muốn giá trị, bạn phải chuyển đổi tham chiếu bằng cách sử dụng *age.

JavaScript là ngôn ngữ cấp cao thực hiện chuyển đổi này cho bạn.

Vì vậy, mặc dù các đối tượng được truyền bằng tham chiếu, ngôn ngữ sẽ chuyển đổi tham số tham chiếu thành giá trị. Bạn không cần phải sử dụng &, trên định nghĩa hàm, để chuyển nó bằng tham chiếu *, trên thân hàm, cũng không cần phải chuyển đổi tham chiếu thành giá trị, JavaScript sẽ làm điều đó cho bạn.

Đó là lý do tại sao khi bạn cố gắng thay đổi một đối tượng bên trong một hàm, bằng cách thay thế giá trị của nó (tức là age = {value:5}), thay đổi sẽ không tồn tại, nhưng nếu bạn thay đổi thuộc tính của nó (tức là age.value = 5), thì nó sẽ xảy ra.

Tìm hiểu thêm

Related questions

MORE COOL STUFF

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

8 công dụng tuyệt vời của Baking Soda và Giấm

8 công dụng tuyệt vời của Baking Soda và Giấm

Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.

Trong Saturday Night Live, The Bachelor is Bland và Tina Fey trở lại với vai 'Crazy' Sarah Palin

Trong Saturday Night Live, The Bachelor is Bland và Tina Fey trở lại với vai 'Crazy' Sarah Palin

Sau khi Sarah Palin tán thành Donald Trump vào đầu tuần này, gần như không thể tránh khỏi việc Tina Fey sẽ trở lại Saturday Night Live để thăm lại ấn tượng Palin cổ điển của cô. Và Fey chắc chắn đã không làm thất vọng, cô ấy đã đưa ra một lời khen ngợi không hề nhẹ về bài phát biểu chứng thực Iowa quanh co và khó hiểu của Palin trong khi Trump của Darrell Hammond đưa ra bình luận xuyên suốt.

Đây có phải là sự khởi đầu cho sự kết thúc của việc giam giữ Brittney Griner?

Đây có phải là sự khởi đầu cho sự kết thúc của việc giam giữ Brittney Griner?

Brittney Griner (r.) Ngay từ đầu, thân phận của Brittney Griner đã là tình huống con tin Mỹ độc nhất trong lịch sử hiện đại.

Tom Brady là bộ tứ vệ đầu tiên cuối cùng có thể giúp Julio Jones có hơn 10 lần chạm bóng trong một mùa giải

Tom Brady là bộ tứ vệ đầu tiên cuối cùng có thể giúp Julio Jones có hơn 10 lần chạm bóng trong một mùa giải

Chúng ta có thể thấy nhiều hơn nữa về một Julio Jones khỏe mạnh trong khu vực cuối năm nay. John Parker Wilson, Greg McElroy, A.

Đó phải là Đức

Đó phải là Đức

Đối với đội tuyển Anh, không có kẻ thủ ác nào lớn hơn Hầu hết các cổ động viên Anh, nếu không muốn nói là tất cả, hẳn sẽ phải gật gù khi tiếng còi mãn cuộc của trận bán kết lượt về W Euro 2022 vang lên. Bởi vì nó báo hiệu rằng Đức sẽ chờ đợi ở Wembley trong trận chung kết với Anh và là điều duy nhất giữa Anh và chiếc cúp lớn đầu tiên của đội tuyển nữ.

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Vụ kiện, nêu tên một số học khu, lập luận rằng dự luật "Không nói đồng tính" được ban hành gần đây của Florida "có hiệu quả im lặng và xóa bỏ học sinh và gia đình LGBTQ +"

Đường băng hạ cánh

Đường băng hạ cánh

Cuối hè đầu thu là mùa hoài niệm. Những chiếc đèn đường chiếu ánh sáng của chúng qua những con đường đẫm mưa, và những chiếc lá dưới chân - màu đỏ cam tắt trong bóng chạng vạng - là lời nhắc nhở về những ngày đã qua.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Tôi ghét từ "tàu đắm". Mọi người cảm thấy thoải mái trong la bàn đạo đức của riêng mình, và khi làm như vậy, họ thấy mình vượt qua sự phán xét.

Language