2008-09-23 69 views
33

JavaScript cho phép các hàm được coi là đối tượng - nếu trước tiên bạn xác định biến là hàm, sau đó bạn có thể thêm thuộc tính vào hàm đó. Làm thế nào để bạn làm ngược lại, và thêm một chức năng cho một "đối tượng"?Làm thế nào để chuyển đổi một "đối tượng" thành một hàm trong JavaScript?

này hoạt động:

var foo = function() { return 1; }; 
foo.baz = "qqqq"; 

Tại thời điểm này, foo() gọi hàm, và foo.baz có giá trị "qqqq".

Tuy nhiên, nếu bạn thực hiện phần gán thuộc tính trước, thì sau đó bạn gán một hàm cho biến đó như thế nào?

var bar = { baz: "qqqq" }; 

tôi có thể làm gì bây giờ để sắp xếp cho bar.baz có giá trị "qqqq" bar() để gọi hàm?

+0

Tôi không hiểu sự cần thiết phải làm điều này. Bạn có thể đưa ra một ví dụ cụ thể về những gì bạn đang cố gắng đạt được không? – Geoff

+1

Tôi không thể nghĩ đến việc sử dụng cho biểu mẫu thứ hai ngay bây giờ. Việc đầu tiên là phần nào hữu ích cho các biến tĩnh (mặc dù đóng cửa cũng sẽ làm). Tôi chủ yếu là hỏi vì tôi không thể nghĩ ra một cách để đạt được nó mà không cần sao chép các thuộc tính trên, mà là không may vì chúng là các hình thức song song. – mjs

+0

Nghe có vẻ như bạn đang hy vọng rằng vì bạn có thể gán một phương thức cho một đối tượng Javascript, bạn cũng có thể gán một toán tử quá tải. Tôi không biết Javascript vì vậy tôi không biết câu trả lời, nhưng may mắn ... –

Trả lời

26

Thật dễ bị nhầm lẫn ở đây, nhưng bạn không thể (dễ dàng hoặc rõ ràng hoặc xa như tôi biết) làm những gì bạn muốn. Hy vọng rằng điều này sẽ giúp mọi thứ rõ ràng.

Đầu tiên, mọi đối tượng trong Javascript được kế thừa từ đối tượng Đối tượng.

//these do the same thing 
var foo = new Object(); 
var bar = {}; 

Thứ hai, chức năng đối tượng trong Javascript. Cụ thể, chúng là đối tượng hàm. Đối tượng Hàm kế thừa từ đối tượng Object. Kiểm tra các Function constructor

var foo = new Function(); 
var bar = function(){}; 
function baz(){}; 

Khi bạn khai báo một biến là một "đối tượng" bạn không (một cách dễ dàng hoặc rõ ràng hoặc như xa như tôi biết) có thể chuyển nó sang một đối tượng Function. Bạn cần khai báo một đối tượng mới của kiểu Function (với hàm tạo hàm, gán một biến một hàm nặc danh, vv), và sao chép qua bất kỳ thuộc tính nào của các phương thức từ đối tượng cũ của bạn.

Cuối cùng, dự đoán một câu hỏi có thể, ngay cả khi một cái gì đó được khai báo là một hàm, bạn không thể (theo như tôi biết) thay đổi hàm/nguồn.

+2

chỉ là một lưu ý phụ, bạn không thể thay đổi nguồn, nhưng bạn CAN xác định lại chức năng (ví dụ: ghi đè lên nó) bất cứ lúc nào. – scunliffe

+0

Tất cả các đối tượng kế thừa từ 'Object.prototype' (nếu không được đặt rõ ràng cho đối tượng khác). Các đối tượng hàm được kế thừa từ 'Function.prototype'. –

0

JavaScript cho phép chức năng là được coi là đối tượng - bạn có thể thêm thuộc tính vào hàm. Làm thế nào để bạn làm điều ngược lại và thêm hàm vào đối tượng ?

Bạn có vẻ hơi bối rối. Các hàm, trong JavaScript, là các đối tượng. Và biến số biến số. Bạn sẽ không mong đợi điều này hoạt động:

var three = 3; 
three = 4; 
assert(three === 3); 

... vậy tại sao bạn mong đợi việc gán một hàm cho biến của bạn bằng cách nào đó sẽ giữ nguyên giá trị trước đó? Có lẽ một số chú thích sẽ làm rõ mọi thứ cho bạn:

// assigns an anonymous function to the variable "foo" 
var foo = function() { return 1; }; 
// assigns a string to the property "baz" on the object 
// referenced by "foo" (which, in this case, happens to be a function) 
foo.baz = "qqqq"; 
+0

Chính xác, hãy xem nhận xét của anh ấy về câu trả lời của tôi - Tôi nghĩ anh ấy hơi bị mất ... –

+1

Bài tập thứ hai trong câu hỏi ban đầu là khó hiểu; Tôi đã xóa ngay bây giờ. Sau 'bar = {baz:" qqqq "}', làm thế nào bạn có thể sắp xếp cho 'bar()' để được gọi là một hàm? – mjs

+0

Bạn không. Bạn vừa gán một đối tượng cho nó mà * KHÔNG * một hàm - bạn có thể bắt đầu lại (và gán một hàm cho nó), hoặc bạn có thể tiếp tục cuộc sống của mình. – Shog9

20

Có vẻ như đây không phải là cách tiêu chuẩn để thực hiện, nhưng điều này có hiệu quả.

TẠI SAO tuy nhiên, là câu hỏi.

function functionize(obj , func) 
{ 
    out = func; 
    for(i in obj){ out[i] = obj[i]; } ; 
    return out; 
} 

x = { a: 1, b: 2 }; 
x = functionize(x , function(){ return "hello world"; }); 
x() ==> "hello world" 

Có chỉ đơn giản là không có cách nào khác để đạt được điều này, làm

x={} 
x() 

SẼ trả về một "lỗi gõ". bởi vì "x" là một "đối tượng" và bạn không thể thay đổi nó. của nó là hợp lý như cố gắng làm

x = 1 
x[50] = 5 
print x[50] 

nó sẽ không hoạt động. 1 là một số nguyên. số nguyên không có phương thức mảng. bạn không thể làm được.

+5

Tại sao công trình này không phải là một bí ẩn. Bạn chỉ đang thay thế x bằng hàm. –

+0

Vâng, nhưng điều này cũng sao chép tất cả các thuộc tính của 'x' vào hàm trước khi thay thế x bằng hàm. Mặc dù tôi nghĩ (đã một vài năm kể từ khi tôi trả lời câu hỏi này) rằng "Tại sao" nhiều hơn "Một hàm là một đối tượng hơi khó hiểu" –

1

Sử dụng một biến tạm thời:

var xxx = function()... 

sau đó sao chép tất cả các thuộc tính từ đối tượng gốc:

for (var p in bar) { xxx[p] = bar[p]; } 

cuối cùng phân công lại chức năng mới với các thuộc tính cũ để biến ban đầu:

bar = xxx; 
-1
var bar = { 
    baz: "qqqq", 
    runFunc: function() { 
     return 1; 
    } 
}; 

alert(bar.baz); // should produce qqqq 
alert(bar.runFunc()); // should produce 1 

Tôi nghĩ bạn đang tìm kiếm điều này.

cũng có thể được viết như thế này:

function Bar() { 
    this.baz = "qqqq"; 
    this.runFunc = function() { 
     return 1; 
    } 
} 

nBar = new Bar(); 

alert(nBar.baz); // should produce qqqq 
alert(nBar.runFunc()); // should produce 1 
+0

Điều này không chạm vào câu hỏi ban đầu chút nào, đó là cách chuyển đổi một đối tượng đơn giản thành một hàm runnable. Câu trả lời của bạn chỉ đơn giản là gán một hàm làm thuộc tính của một đối tượng. – krb686

2

loại đối tượng là chức năng và một đối tượng chính nó là một chức năng instantiation.

javascript:alert([Array, Boolean, Date, Function, 
         Number, Object, RegExp, String].join('\n\n')) 

hiển thị (trong FireFox):

function Array() { 
    [native code] 
} 

function Boolean() { 
    [native code] 
} 

function Date() { 
    [native code] 
} 

function Function() { 
    [native code] 
} 

function Number() { 
    [native code] 
} 

function Object() { 
    [native code] 
} 

function RegExp() { 
    [native code] 
} 

function String() { 
    [native code] 
} 

Đặc biệt, lưu ý một đối tượng Function, function Function() { [native code] }, được định nghĩa là một mối quan hệ tái phát (một định nghĩa đệ quy sử dụng chính nó).

Ngoài ra, lưu ý rằng answer 124402#124402 chưa hoàn thành về 1[50]=5. Hàm này gán một thuộc tính cho đối tượng Number và Javascript hợp lệ. Quan sát,

javascript: 
    alert([ [].prop="a", true.sna="fu", (new Date()).tar="fu", 
        function(){}.fu="bar", 123[40]=4, {}.forty=2, 
         /(?:)/.forty2="life", "abc".def="ghi" ].join("\t")) 

màn

a fu fu bar 4 2 life ghi 

giải thích và thực hiện một cách chính xác theo của javascript "Rules of Engagement".

Tất nhiên, luôn có nếp nhăn và biểu hiện theo số =. Một đối tượng thường "ngắn mạch" với giá trị của nó thay vì một thực thể chính thức khi được gán cho một biến.Đây là vấn đề với các đối tượng Boolean và các giá trị boolean.

Nhận dạng đối tượng rõ ràng giải quyết vấn đề này.

javascript: x=new Number(1); x[50]=5; alert(x[50]); 

"quá tải" là một bài tập hoàn toàn hợp pháp javascript và xác nhận một cách rõ ràng với các cơ chế như prototyping dù đang hoang mang có thể là một mối nguy hiểm.

Cuối cùng lưu ý:

javascript: alert( 123 . x = "not" ); 

javascript: alert((123). x = "Yes!"); /*()'s elevate to full object status */ 
1
var A = function(foo) {                          
    var B = function() {                          
    return A.prototype.constructor.apply(B, arguments); 
    }; 
    B.prototype = A.prototype;                         
    return B;                             
}; 
+7

Chính xác điều này đang làm gì? – netpoetica

0

NB: Đăng viết theo phong cách của cách tôi giải quyết vấn đề này. Tôi không chắc chắn 100% nó có thể sử dụng trong trường hợp của OP.

Tôi tìm thấy bài đăng này trong khi tìm cách chuyển đổi các đối tượng được tạo trên máy chủ và được gửi đến máy khách bằng JSON/ajax.

Điều gì khiến tôi có hiệu quả trong cùng một tình huống như OP, một đối tượng mà tôi muốn chuyển đổi thành một hàm để có thể tạo các phiên bản của nó trên máy khách.

Cuối cùng tôi đã đưa ra với điều này, mà đang làm việc (cho đến nay ít nhất):

var parentObj = {} 

parentObj.createFunc = function (model) 
{ 
    // allow it to be instantiated 
    parentObj[model._type] = function() 
    { 
     return (function (model) 
     { 
      // jQuery used to clone the model 
      var that = $.extend(true, null, model); 
      return that; 
     })(model); 
    } 
} 

nào sau đó có thể được sử dụng như:

var data = { _type: "Example", foo: "bar" }; 
parentObject.createFunc(data); 
var instance = new parentObject.Example(); 

Trong trường hợp của tôi, tôi thực sự muốn để có các hàm kết hợp với các cá thể đối tượng kết quả, và cũng có thể truyền vào các tham số tại thời điểm khởi tạo nó.

Vì vậy, mã của tôi là:

var parentObj = {}; 
// base model contains client only stuff 
parentObj.baseModel = 
{ 
    parameter1: null, 
    parameter2: null, 
    parameterN: null, 
    func1: function() 
    { 
     return this.parameter2; 
    }, 
    func2: function (inParams) 
    { 
     return this._variable2; 
    } 
} 

// create a troop type 
parentObj.createModel = function (data) 
{ 
    var model = $.extend({}, parentObj.baseModel, data); 
    // allow it to be instantiated 
    parentObj[model._type] = function(parameter1, parameter2, parameterN) 
    { 
     return (function (model) 
     { 
      var that = $.extend(true, null, model); 
      that.parameter1 = parameter1; 
      that.parameter2 = parameter2; 
      that.parameterN = parameterN; 
      return that; 
     })(model); 
    } 
} 

Và được gọi như sau:

// models received from an AJAX call 
var models = [ 
{ _type="Foo", _variable1: "FooVal", _variable2: "FooVal" }, 
{ _type="Bar", _variable1: "BarVal", _variable2: "BarVal" }, 
{ _type="FooBar", _variable1: "FooBarVal", _variable2: "FooBarVal" } 
]; 

for(var i = 0; i < models.length; i++) 
{ 
    parentObj.createFunc(models[i]); 
} 

Và sau đó họ có thể được sử dụng:

var test1 = new parentObj.Foo(1,2,3); 
var test2 = new parentObj.Bar("a","b","c"); 
var test3 = new parentObj.FooBar("x","y","z"); 

// test1.parameter1 == 1 
// test1._variable1 == "FooVal" 
// test1.func1() == 2 

// test2.parameter2 == "a" 
// test2._variable2 == "BarVal" 
// test2.func2() == "BarVal" 

// etc 
Các vấn đề liên quan