2015-01-02 28 views
5

Tôi đang cố gắng mở rộng chuỗi để cung cấp băm của chính nó. Tôi đang sử dụng thư viện mật mã Node.js.Tại sao 'this' bên trong String.prototype tham chiếu đến một kiểu đối tượng, không phải kiểu chuỗi?

tôi mở rộng chuỗi như thế này:

String.prototype.hashCode = function() { 
    return getHash(this); 
}; 

và tôi có một hàm getHash trông như thế này:

function getHash(testString) { 
    console.log("type is" + typeof(testString)); 
    var crypto = require('crypto'); 
    var hash = crypto.createHash("sha256"); 
    hash.update(testString); 
    var result = hash.digest('hex'); 
    return result; 
} 

Chức năng hoạt động tốt khi gọi trực tiếp, như trong

var s = "Hello world"; 
console.log(getHash(s)); 

nhưng khi tôi thử:

var s = "ABCDE"; 
console.log(s.hashCode()); 

cuộc gọi phương thức không thành công. Có vẻ như this trong các String.prototype.hashCode được xác định là một đối tượng khi được gọi là crypto.hash.update, nhưng một chuỗi được mong đợi. Tôi nghĩ rằng this bên trong String.prototype sẽ là chuỗi chính nó, nhưng đối với một số lý do nó trông giống như một đối tượng để getHash(). Làm thế nào tôi có thể sửa chữa nó?

Trả lời

7

this không thể của một loại nguyên thủy bên ngoài strict mode, vì vậy nó trở thành một Stringwrapper type, mà không hành xử giống như một chuỗi nguyên thủy ở tất cả (đặc biệt như xa như typeof và bình đẳng - cả hai chặt chẽ và lỏng lẻo - đi). Bạn có thể cast nó:

String.prototype.hashCode = function() { 
    return getHash('' + this); 
};

nơi '' + được sử dụng để đúc bất kỳ giá trị cho một chuỗi nguyên thủy. (String(this) cũng làm việc, nếu bạn cảm thấy rằng đó là rõ ràng hơn.)

Bạn cũng có thể đi vào chế độ nghiêm ngặt, nơi mà mọi thứ chỉ có ý nghĩa:

String.prototype.hashCode = function() { 
    'use strict'; 
    return getHash(this); 
}; 
+2

Tôi sẽ chỉ sử dụng 'sử dụng nghiêm ngặt', nhưng vẫn để lại nhận xét giải thích lý do tại sao nó được yêu cầu. Có khả năng hầu hết các nhà bảo trì sẽ không biết lý do. – Marcelo

2

Khi bạn gọi một phương thức trên một biến nguyên thủy loại, được gọi là auto-boxing được thực hiện. Quá trình đó bao bọc một giá trị nguyên thủy vào đối tượng tương ứng, ví dụ 'asdf' đến new String('asdf'). Vì các giá trị nguyên thủy về kỹ thuật không có các phương thức các thuộc tính, chúng được lưu trữ trong các nguyên mẫu đối tượng. Với auto-boxing bạn có thể gọi các phương thức trên các giá trị nguyên thủy. Và trong một phương thức, this luôn là đối tượng có phương thức đó.

Nếu bạn muốn truy cập giá trị nguyên thủy trong một phương pháp, bạn có thể chuyển nó làm đối số, hoặc như bạn muốn, hãy truy lục giá trị nguyên thủy từ this. Ví dụ:

var str = new String('asdf') // String {0: "a", 1: "s", 2: "d", 3: "f", length: 4, formatUnicorn: function, truncate: function, splitOnLast: function, [[PrimitiveValue]]: "asdf"} 
String(str) // 'asdf' 

var num = new Number(123) // Number {[[PrimitiveValue]]: 123} 
Number(num) // 123 

var bool = new Boolean(true) // Boolean {[[PrimitiveValue]]: true} 
Boolean(bool) // true 
Các vấn đề liên quan