tham chiếu / bí danh biến javascript


89

Có thể trong javascript để gán bí danh / tham chiếu cho một var địa phương nào đó không?

Ý tôi là một cái gì đó giống như C:

function foo() {
  var x = 1;
  var y = &x;
  y++;
  alert(x); // prints 2 
}

= CHỈNH SỬA =

Có thể đặt bí danh đối số.callee trong mã này không ?:

function foo() {
  arguments.callee.myStaticVar = arguments.callee.myStaticVar || 0;
  arguments.callee.myStaticVar++;
  return arguments.callee.myStaticVar;
}

5
Câu trả lời đơn giản là không. Nhưng tôi có cảm giác rằng ai đó ở SO sẽ đến với một bản hack để làm điều này :)
Amarghosh

Câu trả lời:


173

Trong JavaScript, các kiểu nguyên thủy như số nguyên và chuỗi được chuyển bằng giá trị trong khi các đối tượng được chuyển bằng tham chiếu. Vì vậy, để đạt được điều này, bạn cần sử dụng một đối tượng:

// declare an object with property x
var obj = { x: 1 };
var aliasToObj = obj;
aliasToObj.x ++;
alert( obj.x ); // displays 2

Nhanh quá =) Tôi muốn tạo một bí danh cho các đối số.callee bên trong hàm của mình (chỉ để tránh việc nhập các đối số.callee mỗi lần). có khả thi với phương pháp này không? Nếu tôi hiểu, tôi có thể đặt bí danh là "đối số" nhưng dù sao tôi vẫn phải viết "callee", phải không?
gpilotino

9
@Darin: điều này hơi đơn giản hóa nó. Đó là kiểu bất biến so với kiểu có thể thay đổi, chứ không phải kiểu nguyên thủy vs đối tượng. Trong JavaScript, mọi thứ đều là một đối tượng ở một số dạng.
Crescent Fresh

7
Trong JS, tham chiếu được truyền theo giá trị. Có sự khác biệt giữa "chuyển qua tham chiếu" và "chuyển qua tham chiếu theo giá trị". Trong Javascript, việc chuyển các tham số bằng tham chiếu không được báo cáo.
Corneliu

15

Điều này có thể xảy ra ở một mức độ nào đó, bạn có thể tạo bí danh cho một biến bằng cách sử dụng các bao đóng:

Function.prototype.toString = function() {
    return this();
}

var x = 1;
var y = function() { return x }
x++;
alert(y); // prints 2, no need for () because of toString redefinition 

1
Tôi tin rằng "alert (y); // bản in 2" nên là: "alert (y ()); // bản in 2" Bạn phải thực sự gọi hàm để nhận kết quả. Quá tệ, vì cú pháp được đề xuất sẽ hữu ích trong một số trường hợp nhất định.
Nathan Labenz

3
Định nghĩa lại toString đó là có lý do, vì vậy alert(y)thực tế là đúng. Mặc dù định nghĩa lại các phương thức nguyên mẫu của Hàm là một phong cách rất tệ. Nhưng này, nó hoạt động!
metalim

8

Bạn có thể đặt bí danh gì đó hay không tùy thuộc vào kiểu dữ liệu. Các đối tượng, mảng và hàm sẽ được xử lý bằng tham chiếu và có thể sử dụng răng cưa. Các loại khác về cơ bản là nguyên tử và biến lưu trữ giá trị thay vì tham chiếu đến một giá trị.

đối số.callee là một hàm, và do đó bạn có thể có một tham chiếu đến nó và sửa đổi đối tượng được chia sẻ đó.

function foo() {
  var self = arguments.callee;
  self.myStaticVar = self.myStaticVar || 0;
  self.myStaticVar++;
  return self.myStaticVar;
}

Lưu ý rằng nếu trong đoạn mã trên mà bạn định nói self = function() {return 42;};thì sau đó selfsẽ tham chiếu đến một đối tượng khác với đối tượngarguments.callee vẫn là một tham chiếu tới foo. Khi bạn có một đối tượng ghép, toán tử gán thay thế tham chiếu, nó không thay đổi đối tượng được tham chiếu. Với các giá trị nguyên tử, một trường hợp như y++tương đương với y = y + 1, là gán một số nguyên 'mới' cho biến.


đó là chưa kể arguments.calleeđã có bí danh, là tên của hàm. Trong ví dụ này, bạn chỉ có thể sử dụng foo.myStaticVar(có lẽ đây không phải là trường hợp trở lại trong năm 2009?)
aljgom

1

chỉnh sửa câu trả lời trước đây của tôi: nếu bạn muốn đếm số lần gọi của một hàm, bạn có thể muốn thử:

var countMe = ( function() {
  var c = 0;

  return function() {
    c++;
    return c;
  }
})();

alert(countMe()); // Alerts "1"
alert(countMe()); // Alerts "2"

Ở đây, c đóng vai trò là bộ đếm và bạn không cần phải sử dụng đối số.callee.


hoặc bạn có thể sử dụng một biến tĩnh countMe = function f(){ return ++f.c || (f.c = 1); }
aljgom

1

Mở rộng trên bài đăng của user187291 , bạn cũng có thể sử dụng getters / setters để tránh phải sử dụng các hàm.

var x = 1;
var ref = {
    get x()  { return x; },
    set x(v) { x = v; }
};
(ref.x)++;
console.log(x); // prints '2'
x--;
console.log(ref.x); // prints '1'

0

vào năm 2019, tôi cần viết các plugin jquery được rút gọn vì vậy tôi cũng cần nó với bí danh này và do đó, thử nghiệm các ví dụ này và các ví dụ khác, từ các nguồn khác, tôi đã tìm thấy một cách mà không cần sao chép trong bộ nhớ của toàn bộ đối tượng mà chỉ tạo một tham chiếu. Tôi đã thử nghiệm điều này với firefox và xem bộ nhớ tab của trình quản lý tác vụ trên firefox trước đây. Mã là:

var {p: d} ={p: document};
console.log(d.body);

Điều này không chuyển bất cứ thứ gì bằng tham chiếu, bạn chỉ có thể truyền trực tiếp tài liệu (vốn đã là tham chiếu đến một đối tượng và được truyền theo giá trị). Cơ cấu hủy không tạo bí danh.
Nhớ Monica
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.