Chức năng nạp chồng trong Javascript - Thực tiễn tốt nhất


783

Cách tốt nhất để quá tải chức năng giả trong Javascript là gì?

Tôi biết không thể quá tải các chức năng trong Javascript như trong các ngôn ngữ khác. Nếu tôi cần một chức năng với hai cách sử dụng foo(x)foo(x,y,z)đó là cách tốt nhất / ưa thích:

  1. Sử dụng tên khác nhau ở nơi đầu tiên
  2. Sử dụng các đối số tùy chọn như y = y || 'default'
  3. Sử dụng số lượng đối số
  4. Kiểm tra các loại đối số
  5. Hoặc thế nào?

14
Có lẽ sẽ hữu ích khi hỏi tại sao bạn nghĩ rằng bạn cần quá tải chức năng để bắt đầu. Tôi nghĩ rằng điều đó sẽ giúp chúng ta gần hơn với một giải pháp thực sự.
Breton

1
Điều này đã bị đóng, nhưng tôi làm như sau: this.selectBy = {dụ: selectByInstance, // Hàm văn bản: selectByText, // Giá trị hàm: selectByValue // Function};
Tù nhân ZERO

Câu trả lời của tôi cho thấy cách thực hiện quá tải chức năng thời gian chạy, nó có một hình phạt tốc độ và tôi không khuyên bạn nên làm điều đó để đi xung quanh đặc tả của Javascript. Quá tải chức năng thực sự là một nhiệm vụ biên dịch thời gian, tôi chỉ cung cấp câu trả lời cho mục đích học thuật và để nó tùy ý bạn có nên sử dụng nó trong mã hay không.
Keldon Alleyne

2
Trong trường hợp nó hữu ích, tôi đã xây dựng một khung js nhẹ cho phép nạp chồng phương thức dựa trên kiểu. Rõ ràng các cảnh báo tương tự được áp dụng liên quan đến hiệu suất, nhưng nó hoạt động tốt cho nhu cầu của tôi cho đến nay và vẫn còn khá nhiều chỗ để cải thiện: blog.pebbl.co.uk/2013/01/descripejs.html#methodoverloading
Pebbl

Câu trả lời:


602

Cách tốt nhất để thực hiện nạp chồng hàm với các tham số không phải là kiểm tra độ dài đối số hoặc kiểu; kiểm tra các loại sẽ chỉ làm cho mã của bạn chậm và bạn có niềm vui của Mảng, null, Đối tượng, v.v.

Điều mà hầu hết các nhà phát triển làm là giải quyết một đối tượng là đối số cuối cùng cho các phương thức của họ. Đối tượng này có thể giữ bất cứ điều gì.

function foo(a, b, opts) {
  // ...
  if (opts['test']) { } //if test param exists, do something.. 
}


foo(1, 2, {"method":"add"});
foo(3, 4, {"test":"equals", "bar":"tree"});

Sau đó, bạn có thể xử lý nó bằng mọi cách bạn muốn trong phương pháp của bạn. [Chuyển đổi, nếu-khác, v.v.]


43
Bạn có thể cung cấp một triển khai mẫu của foo () minh họa cách các tham số "opts" này được sử dụng / tham chiếu không?
Moe Howard

24
Moe // Nó có thể như thế này; if(opts['test']) //if test param exists, do something.. if(opts['bar']) //if bar param exists, do something
Deckard

80
Đây không phải là quá tải chức năng. Quá tải chức năng là có hai chức năng riêng biệt có cùng tên nhưng tham số khác nhau. Những gì bạn đang mô tả chỉ là một chức năng với một đối số ở cuối.
d512

66
@ user1334007 không thể có chức năng nạp chồng như bạn làm trong Java / .NET. Vâng, đây không phải là "chính xác" quá tải, nhưng nó thực hiện công việc.
eprebello

18
Tôi ngạc nhiên không ai hỏi điều này cả: tại sao kiểm tra arguments.lengthkhông được khuyến nghị? Ngoài ra, tôi đã từng đến đây và đọc Điều mà hầu hết các nhà phát triển làm là ... , nhưng tôi chắc chắn đây là nơi duy nhất tôi thấy điều đó được thực hiện. Phương pháp đó cũng làm hỏng tính tổng hợp cú pháp của việc 'quá tải'!
c24w

169

Tôi thường làm điều này:

C #:

public string CatStrings(string p1)                  {return p1;}
public string CatStrings(string p1, int p2)          {return p1+p2.ToString();}
public string CatStrings(string p1, int p2, bool p3) {return p1+p2.ToString()+p3.ToString();}

CatStrings("one");        // result = one
CatStrings("one",2);      // result = one2
CatStrings("one",2,true); // result = one2true

Tương đương JavaScript:

function CatStrings(p1, p2, p3)
{
  var s = p1;
  if(typeof p2 !== "undefined") {s += p2;}
  if(typeof p3 !== "undefined") {s += p3;}
  return s;
};

CatStrings("one");        // result = one
CatStrings("one",2);      // result = one2
CatStrings("one",2,true); // result = one2true

Ví dụ cụ thể này thực sự thanh lịch hơn trong javascript so với C #. Các tham số không được chỉ định là 'không xác định' trong javascript, đánh giá thành sai trong câu lệnh if. Tuy nhiên, định nghĩa hàm không truyền đạt thông tin mà p2 và p3 là tùy chọn. Nếu bạn cần quá tải, jQuery đã quyết định sử dụng một đối tượng làm tham số, ví dụ, jQuery.ajax (tùy chọn). Tôi đồng ý với họ rằng đây là cách tiếp cận tài liệu rõ ràng và mạnh mẽ nhất để quá tải, nhưng tôi hiếm khi cần nhiều hơn một hoặc hai tham số tùy chọn nhanh.

EDIT: đã thay đổi kiểm tra IF theo đề xuất của Ian


16
Các tham số không được chỉ định là undefinedtrong JS, không phải null. Là một cách thực hành tốt nhất, bạn không bao giờ nên đặt bất cứ điều gì undefined, vì vậy nó không phải là vấn đề miễn là bạn thay đổi bài kiểm tra của mình p2 === undefined.
Tamzin Blake

3
Nếu bạn vượt qua falsenhư là đối số cuối cùng thì nó sẽ không "false"kết thúc đến cùng, bởi vì if(p3)nhánh sẽ không.
dreamlax

5
Chỉ cần một ghi chú nhanh, typeof p2 === "undefined"có lẽ bạn là mặt trái của những gì bạn mong đợi trong ví dụ của bạn, tôi nghĩ đó typeof p2 !== "undefined"là những gì bạn dự định. Ngoài ra, tôi có thể đề nghị được nối chuỗi, số và boolean mà bạn thực sự làmp2 === "number"; p3 === "boolean"
WillFM

8
Tôi thích làm điều này: p3 = p3 || 'giá trị mặc định';
Dorian

3
Ý nghĩa của ===và là !==gì? Tại sao không chỉ sử dụng ==!=?
Ricardo Cruz

76

Không có quá tải chức năng thực sự trong JavaScript vì nó cho phép vượt qua bất kỳ số lượng tham số thuộc bất kỳ loại nào. Bạn phải kiểm tra bên trong hàm có bao nhiêu đối số đã được thông qua và chúng là loại gì.


1
John Resig (của jQuery) đã từng thử điều này, nhưng nỗ lực này hoàn toàn mang tính học thuật và không mang lại lợi ích thực sự nào.
scunliffe

14
Chức năng quá tải của John Resig tại đây ejohn.org/blog/javascript-method-overloading
Terrance

@Terrance: Tôi cũng thích phương pháp của Resig. Nó hoạt động như một say mê. Tôi chỉ cần tìm một cách để tạo một thử nghiệm cho nó để xác nhận các trường hợp sử dụng.
chrisvillanueva

"Chức năng này sẽ không thay đổi thế giới, nhưng nó ngắn gọn, súc tích và sử dụng một tính năng JavaScript tối nghĩa - vì vậy nó chiến thắng trong cuốn sách của tôi." :-)
Frerich Raabe

67

Câu trả lời đúng là KHÔNG CÓ TẢI XUỐNG TRONG JAVASCRIPT.

Kiểm tra / Chuyển đổi bên trong chức năng không phải là TẢI XUỐNG.

Khái niệm về nạp chồng: Trong một số ngôn ngữ lập trình, nạp chồng hàm hoặc nạp chồng phương thức là khả năng tạo nhiều phương thức cùng tên với các cách triển khai khác nhau. Các lệnh gọi đến một hàm bị quá tải sẽ chạy một triển khai cụ thể của hàm đó phù hợp với ngữ cảnh của cuộc gọi, cho phép một lệnh gọi hàm thực hiện các tác vụ khác nhau tùy theo ngữ cảnh.

Ví dụ, doTask () và doTask (đối tượng O) là các phương thức bị quá tải. Để gọi cái sau, một đối tượng phải được truyền dưới dạng tham số, trong khi đối tượng trước không yêu cầu tham số và được gọi với trường tham số trống. Một lỗi phổ biến sẽ là gán giá trị mặc định cho đối tượng trong phương thức thứ hai, điều này sẽ dẫn đến lỗi cuộc gọi không rõ ràng, vì trình biên dịch sẽ không biết nên sử dụng phương thức nào trong hai phương thức.

https://en.wikipedia.org/wiki/Function_overloading

Tất cả các triển khai được đề xuất là tuyệt vời, nhưng sự thật phải nói, không có triển khai riêng cho JavaScript.


4
cuối cùng là một câu trả lời bình thường! KHÔNG CÓ TẢI XUỐNG TRONG JAVASCRIPT.
Razvan Tudorica

4
OP yêu cầu một cách để quá tải giả .
Trò chơi Ateur

Như tôi đã nói trước đây, chúng tôi ở đây để giáo dục mọi người, chúng tôi không chỉ đưa ra câu trả lời cho họ mà không xác minh rằng những gì họ đang hỏi là đúng.
Marco

27

Có hai cách bạn có thể tiếp cận điều này tốt hơn:

  1. Vượt qua một từ điển (mảng kết hợp) nếu bạn muốn để lại nhiều sự linh hoạt

  2. Lấy một đối tượng làm đối số và sử dụng kế thừa dựa trên nguyên mẫu để thêm linh hoạt.


1
tuy nhiên, đây là suy nghĩ ban đầu của tôi, nếu chức năng bạn đang tạo sẽ được sử dụng trong thư viện hoặc bởi những người khác, việc liệt kê các giá trị rõ ràng có thể hữu ích
roberthuttinger

19

Đây là một cách tiếp cận cho phép nạp chồng phương thức thực bằng các kiểu tham số, được hiển thị bên dưới:

Func(new Point());
Func(new Dimension());
Func(new Dimension(), new Point());
Func(0, 0, 0, 0);

Chỉnh sửa (2018) : Vì điều này được viết vào năm 2011, tốc độ của các cuộc gọi phương thức trực tiếp đã tăng lên rất nhiều trong khi tốc độ của các phương thức quá tải thì không.

Nó không phải là một cách tiếp cận tôi muốn giới thiệu, nhưng nó là một bài tập đáng suy nghĩ để suy nghĩ về cách bạn có thể giải quyết các loại vấn đề này.


Dưới đây là điểm chuẩn của các cách tiếp cận khác nhau - https://jsperf.com/feft-overloading . Nó cho thấy quá tải chức năng (đưa các loại vào tài khoản) có thể chậm hơn khoảng 13 lần trong V8 của Google Chrome kể từ 16.0 (beta) .

Cũng như vượt qua một đối tượng (tức là {x: 0, y: 0} ), người ta cũng có thể thực hiện phương pháp C khi thích hợp, đặt tên cho các phương thức cho phù hợp. Ví dụ: Vector.AddVector (vector), Vector.AddIntegers (x, y, z, ...) và Vector.AddArray (số nguyênArray). Bạn có thể xem các thư viện C, chẳng hạn như OpenGL để đặt tên cảm hứng.

Chỉnh sửa : Tôi đã thêm một điểm chuẩn để vượt qua một đối tượng và kiểm tra đối tượng bằng cả hai 'param' in argarg.hasOwnProperty('param'), quá tải chức năng nhanh hơn nhiều so với việc truyền một đối tượng và kiểm tra các thuộc tính (ít nhất là trong điểm chuẩn này).

Từ quan điểm thiết kế, quá tải chức năng chỉ hợp lệ hoặc hợp lý nếu các tham số quá tải tương ứng với cùng một hành động. Vì vậy, lý do là phải có một phương pháp cơ bản chỉ liên quan đến các chi tiết cụ thể, nếu không, điều đó có thể chỉ ra các lựa chọn thiết kế không phù hợp. Vì vậy, người ta cũng có thể giải quyết việc sử dụng chức năng nạp chồng bằng cách chuyển đổi dữ liệu sang một đối tượng tương ứng. Tất nhiên người ta phải xem xét phạm vi của vấn đề vì không cần thiết kế thiết kế phức tạp nếu ý định của bạn chỉ là in tên, nhưng đối với việc thiết kế khung và thư viện thì suy nghĩ đó là hợp lý.

Ví dụ của tôi xuất phát từ việc triển khai Hình chữ nhật - do đó đề cập đến Kích thước và Điểm. Có lẽ hình chữ nhật có thể thêm một GetRectangle()phương thức vào DimensionPointnguyên mẫu, và sau đó vấn đề nạp chồng hàm được sắp xếp. Còn người nguyên thủy thì sao? Chà, chúng ta có độ dài đối số, hiện là một thử nghiệm hợp lệ vì các đối tượng có một GetRectangle()phương thức.

function Dimension() {}
function Point() {}

var Util = {};

Util.Redirect = function (args, func) {
  'use strict';
  var REDIRECT_ARGUMENT_COUNT = 2;

  if(arguments.length - REDIRECT_ARGUMENT_COUNT !== args.length) {
    return null;
  }

  for(var i = REDIRECT_ARGUMENT_COUNT; i < arguments.length; ++i) {
    var argsIndex = i-REDIRECT_ARGUMENT_COUNT;
    var currentArgument = args[argsIndex];
    var currentType = arguments[i];
    if(typeof(currentType) === 'object') {
      currentType = currentType.constructor;
    }
    if(typeof(currentType) === 'number') {
      currentType = 'number';
    }
    if(typeof(currentType) === 'string' && currentType === '') {
      currentType = 'string';
    }
    if(typeof(currentType) === 'function') {
      if(!(currentArgument instanceof currentType)) {
        return null;
      }
    } else {
      if(typeof(currentArgument) !== currentType) {
        return null;
      }
    } 
  }
  return [func.apply(this, args)];
}

function FuncPoint(point) {}
function FuncDimension(dimension) {}
function FuncDimensionPoint(dimension, point) {}
function FuncXYWidthHeight(x, y, width, height) { }

function Func() {
  Util.Redirect(arguments, FuncPoint, Point);
  Util.Redirect(arguments, FuncDimension, Dimension);
  Util.Redirect(arguments, FuncDimensionPoint, Dimension, Point);
  Util.Redirect(arguments, FuncXYWidthHeight, 0, 0, 0, 0);
}

Func(new Point());
Func(new Dimension());
Func(new Dimension(), new Point());
Func(0, 0, 0, 0);

16

Cách tốt nhất thực sự phụ thuộc vào chức năng và các đối số. Mỗi lựa chọn của bạn là một ý tưởng tốt trong các tình huống khác nhau. Tôi thường thử những thứ này theo thứ tự sau cho đến khi một trong số chúng hoạt động:

  1. Sử dụng các đối số tùy chọn như y = y | | 'mặc định'. Điều này thuận tiện nếu bạn có thể làm điều đó, nhưng nó có thể không phải lúc nào cũng hoạt động thực tế, ví dụ khi 0 / null / không xác định sẽ là một đối số hợp lệ.

  2. Sử dụng số lượng đối số. Tương tự như tùy chọn cuối cùng nhưng có thể hoạt động khi # 1 không hoạt động.

  3. Kiểm tra các loại đối số. Điều này có thể hoạt động trong một số trường hợp số lượng đối số là như nhau. Nếu bạn không thể xác định đáng tin cậy các loại, bạn có thể cần phải sử dụng các tên khác nhau.

  4. Sử dụng tên khác nhau ở nơi đầu tiên. Bạn có thể cần phải làm điều này nếu các tùy chọn khác không hoạt động, không thực tế hoặc để thống nhất với các chức năng liên quan khác.


14

Nếu tôi cần một hàm có hai sử dụng foo (x) và foo (x, y, z) thì cách nào là tốt nhất / ưa thích?

Vấn đề là JavaScript KHÔNG hỗ trợ quá tải phương thức. Vì vậy, nếu nó nhìn thấy / phân tích hai hoặc nhiều hàm có cùng tên, nó sẽ chỉ xem xét hàm được xác định cuối cùng và ghi đè lên các hàm trước đó.

Một trong những cách tôi nghĩ là phù hợp với hầu hết các trường hợp là:

Hãy nói rằng bạn có phương pháp

function foo(x)
{
} 

Thay vì nạp chồng phương thức không thể có trong javascript, bạn có thể định nghĩa một phương thức mới

fooNew(x,y,z)
{
}

và sau đó sửa đổi chức năng thứ 1 như sau -

function foo(arguments)
{
  if(arguments.length==2)
  {
     return fooNew(arguments[0],  arguments[1]);
  }
} 

Nếu bạn có nhiều phương thức quá tải như vậy, hãy xem xét sử dụng switchchứ không chỉ là if-elsecâu lệnh.

( biết thêm chi tiết )

PS: Liên kết trên đi đến blog cá nhân của tôi có thêm chi tiết.


9

Tôi không chắc về cách thực hành tốt nhất, nhưng đây là cách tôi thực hiện:

/*
 * Object Constructor
 */
var foo = function(x) {
    this.x = x;
};

/*
 * Object Protoype
 */
foo.prototype = {
    /*
     * f is the name that is going to be used to call the various overloaded versions
     */
    f: function() {

        /*
         * Save 'this' in order to use it inside the overloaded functions
         * because there 'this' has a different meaning.
         */   
        var that = this;  

        /* 
         * Define three overloaded functions
         */
        var f1 = function(arg1) {
            console.log("f1 called with " + arg1);
            return arg1 + that.x;
        }

        var f2 = function(arg1, arg2) {
             console.log("f2 called with " + arg1 + " and " + arg2);
             return arg1 + arg2 + that.x;
        }

        var f3 = function(arg1) {
             console.log("f3 called with [" + arg1[0] + ", " + arg1[1] + "]");
             return arg1[0] + arg1[1];
        }

        /*
         * Use the arguments array-like object to decide which function to execute when calling f(...)
         */
        if (arguments.length === 1 && !Array.isArray(arguments[0])) {
            return f1(arguments[0]);
        } else if (arguments.length === 2) {
            return f2(arguments[0], arguments[1]);
        } else if (arguments.length === 1 && Array.isArray(arguments[0])) {
            return f3(arguments[0]);
        }
    } 
}

/* 
 * Instantiate an object
 */
var obj = new foo("z");

/*
 * Call the overloaded functions using f(...)
 */
console.log(obj.f("x"));         // executes f1, returns "xz"
console.log(obj.f("x", "y"));    // executes f2, returns "xyz"
console.log(obj.f(["x", "y"]));  // executes f3, returns "xy"

2
@Luis: Tôi đã thêm một số ý kiến ​​hy vọng hữu ích.
cờ vua

6

Tôi chỉ thử điều này, có thể nó phù hợp với nhu cầu của bạn. Tùy thuộc vào số lượng đối số, bạn có thể truy cập một chức năng khác nhau. Bạn khởi tạo nó lần đầu tiên bạn gọi nó. Và bản đồ chức năng được ẩn trong bao đóng.

TEST = {};

TEST.multiFn = function(){
    // function map for our overloads
    var fnMap = {};

    fnMap[0] = function(){
        console.log("nothing here");
        return this;    //    support chaining
    }

    fnMap[1] = function(arg1){
        //    CODE here...
        console.log("1 arg: "+arg1);
        return this;
    };

    fnMap[2] = function(arg1, arg2){
        //    CODE here...
        console.log("2 args: "+arg1+", "+arg2);
        return this;
    };

    fnMap[3] = function(arg1,arg2,arg3){
        //    CODE here...
        console.log("3 args: "+arg1+", "+arg2+", "+arg3);
        return this;
    };

    console.log("multiFn is now initialized");

    //    redefine the function using the fnMap in the closure
    this.multiFn = function(){
        fnMap[arguments.length].apply(this, arguments);
        return this;
    };

    //    call the function since this code will only run once
    this.multiFn.apply(this, arguments);

    return this;    
};

Kiểm tra nó

TEST.multiFn("0")
    .multiFn()
    .multiFn("0","1","2");

5

Vì JavaScript không có chức năng tùy chọn quá tải chức năng có thể được sử dụng thay thế. Nếu có một hoặc hai đối số bắt buộc, tốt hơn hết là tách chúng ra khỏi đối tượng tùy chọn. Dưới đây là một ví dụ về cách sử dụng đối tượng tùy chọn và các giá trị được điền vào giá trị mặc định trong trường hợp nếu giá trị không được truyền trong đối tượng tùy chọn.

    function optionsObjectTest(x, y, opts) {
        opts = opts || {}; // default to an empty options object

        var stringValue = opts.stringValue || "string default value";
        var boolValue = !!opts.boolValue; // coerces value to boolean with a double negation pattern
        var numericValue = opts.numericValue === undefined ? 123 : opts.numericValue;

        return "{x:" + x + ", y:" + y + ", stringValue:'" + stringValue + "', boolValue:" + boolValue + ", numericValue:" + numericValue + "}";

}

đây là một ví dụ về cách sử dụng đối tượng tùy chọn


4

Không có cách nào để chức năng quá tải trong javascript. Vì vậy, tôi khuyên bạn nên thực hiện như sau bằng typeof()phương pháp thay vì nhiều chức năng để nạp chồng giả.

function multiTypeFunc(param)
{
    if(typeof param == 'string') {
        alert("I got a string type parameter!!");
     }else if(typeof param == 'number') {
        alert("I got a number type parameter!!");
     }else if(typeof param == 'boolean') {
        alert("I got a boolean type parameter!!");
     }else if(typeof param == 'object') {
        alert("I got a object type parameter!!");
     }else{
        alert("error : the parameter is undefined or null!!");
     }
}

Chúc may mắn!


24
Vì Chúa! Sử dụng một tuyên bố chuyển đổi!
jedmao

8
Ngoài ra, nếu bạn khăng khăng không sử dụng một công tắc, bạn chỉ nên gọi typeof một lần. var type = typeof param; if (type === 'string') ...
Walter Stabosz

+1 để nhận xét cho "===". Ưu điểm khác của câu lệnh chuyển đổi so với nếu (... == ...) là loại an toàn.
Nathan Cooper

4

GIỚI THIỆU

Cho đến nay đọc qua rất nhiều câu trả lời sẽ khiến bất cứ ai phải đau đầu. Bất cứ ai cố gắng để biết khái niệm sẽ cần phải biết các điều kiện tiên quyết sau đây .

Function overloading Definition, Function Length property,Function argument property

Function overloadingở dạng đơn giản nhất có nghĩa là một hàm thực hiện các nhiệm vụ khác nhau trên cơ sở số lượng đối số đang được truyền cho nó. Đáng chú ý là TASK1, TASK2 và TASK3 được tô sáng bên dưới và đang được thực hiện trên cơ sở số lượng argumentsđược truyền cho cùng một chức năng fooYo.

// if we have a function defined below
function fooYo(){
     // do something here
}
// on invoking fooYo with different number of arguments it should be capable to do different things

fooYo();  // does TASK1
fooYo('sagar'); // does TASK2
fooYo('sagar','munjal'); // does TAKS3

LƯU Ý - JS không cung cấp khả năng sẵn có của chức năng nạp chồng.

Thay thế

John E Resig (người tạo ra JS) đã chỉ ra một giải pháp thay thế sử dụng các điều kiện tiên quyết ở trên để đạt được khả năng thực hiện quá tải chức năng.

Mã dưới đây sử dụng một cách tiếp cận đơn giản nhưng ngây thơ bằng cách sử dụng if-elsehoặc switchtuyên bố.

  • đánh giá argument-lengthtài sản.
  • giá trị khác nhau dẫn đến việc gọi các chức năng khác nhau.

var ninja = {
  whatever: function() {
       switch (arguments.length) {
         case 0:
           /* do something */
           break;
         case 1:
           /* do something else */
           break;
         case 2:
           /* do yet something else */
           break;
       //and so on ...
    } 
  }
}

Một kỹ thuật khác là sạch sẽ và năng động hơn nhiều. Điểm nổi bật của kỹ thuật này là addMethodchức năng chung.

  • chúng ta định nghĩa một hàm addMethodđược sử dụng để thêm các hàm khác nhau vào một đối tượng có cùng tên nhưng các hàm khác nhau .

  • bên dưới addMethodhàm chấp nhận ba tên đối tượng params object, tên hàm namevà hàm mà chúng ta muốn được gọifn .

  • addMethodĐịnh nghĩa bên trong var oldlưu trữ tham chiếu đến trước đó functionđược lưu trữ bởi sự trợ giúp của đóng cửa - một bong bóng bảo vệ.

function addMethod(object, name, fn) {
  var old = object[name];
  object[name] = function(){
    if (fn.length == arguments.length)
      return fn.apply(this, arguments)
    else if (typeof old == 'function')
      return old.apply(this, arguments);
  };
};

  • sử dụng trình gỡ lỗi để hiểu dòng mã.
  • bên dưới addMethodthêm ba hàm mà khi được gọi sử dụng ninja.whatever(x)với số lượng đối số xcó thể là bất cứ thứ gì, tức là để trống hoặc một hoặc nhiều hơn một hàm gọi các hàm khác nhau như được định nghĩa trong khi sử dụng addMethodhàm.

var ninja = {};
debugger;


addMethod(ninja,'whatever',function(){ console.log("I am the one with ZERO arguments supplied") });
addMethod(ninja,'whatever',function(a){ console.log("I am the one with ONE arguments supplied") });
addMethod(ninja,'whatever',function(a,b){ console.log("I am the one with TWO arguments supplied") });


ninja.whatever();
ninja.whatever(1,2);
ninja.whatever(3);


4

Một cách khác để tiếp cận điều này là bằng cách sử dụng biến đặc biệt: đối số , đây là cách triển khai:

function sum() {
    var x = 0;
    for (var i = 0; i < arguments.length; ++i) {
        x += arguments[i];
    }
    return x;
}

để bạn có thể sửa đổi mã này thành:

function sum(){
    var s = 0;
    if (typeof arguments[0] !== "undefined") s += arguments[0];
.
.
.
    return s;
}

3

kiểm tra này Nó rất mát. http://ejohn.org/blog/javascript-method-overloading/ Trick Javascript để cho phép bạn thực hiện các cuộc gọi như thế này:

var users = new Users();
users.find(); // Finds all
users.find("John"); // Finds users by name
users.find("John", "Resig"); // Finds users by first and last name

Xin chào Jaider, hãy xem câu trả lời của tôi, nó chứa mã cho quá tải phương thức javascript thực tế . Tôi đang nói Func(new Point())Func(new Rectangle())sẽ thực thi các chức năng khác nhau. Nhưng tôi phải chỉ ra rằng đây là một hack bẩn, vì quá tải phương thức thực sự là một nhiệm vụ biên dịch thời gian không chạy thời gian.
Keldon Alleyne

3

Chức năng nạp chồng trong Javascript:

Quá tải chức năng là khả năng của một ngôn ngữ lập trình để tạo ra nhiều chức năng cùng tên với các triển khai khác nhau. khi một hàm quá tải được gọi, nó sẽ chạy một hàm thực hiện cụ thể của hàm đó phù hợp với ngữ cảnh của cuộc gọi. Ngữ cảnh này thường là số lượng đối số được nhận và nó cho phép một lệnh gọi hàm hoạt động khác nhau tùy theo ngữ cảnh.

Javascript không có chức năng nạp chồng. Tuy nhiên, hành vi này có thể được mô phỏng theo nhiều cách. Đây là một đơn giản thuận tiện:

function sayHi(a, b) {
  console.log('hi there ' + a);
  if (b) { console.log('and ' + b) } // if the parameter is present, execute the block
}

sayHi('Frank', 'Willem');

Trong các tình huống mà bạn không biết có bao nhiêu đối số bạn sẽ nhận được, bạn có thể sử dụng toán tử còn lại là ba dấu chấm .... Nó sẽ chuyển đổi phần còn lại của các đối số thành một mảng. Cẩn thận với trình duyệt tương thích mặc dù. Đây là một ví dụ:

function foo (a, ...b) {
  console.log(b);
}

foo(1,2,3,4);
foo(1,2);


2

Vì bài đăng này đã chứa rất nhiều giải pháp khác nhau, tôi nghĩ rằng tôi đã đăng một giải pháp khác.

function onlyUnique(value, index, self) {
    return self.indexOf(value) === index;
}

function overload() {
   var functions = arguments;
   var nroffunctionsarguments = [arguments.length];
    for (var i = 0; i < arguments.length; i++) {
        nroffunctionsarguments[i] = arguments[i].length;
    }
    var unique = nroffunctionsarguments.filter(onlyUnique);
    if (unique.length === arguments.length) {
        return function () {
            var indexoffunction = nroffunctionsarguments.indexOf(arguments.length);
            return functions[indexoffunction].apply(this, arguments);
        }
    }
    else throw new TypeError("There are multiple functions with the same number of parameters");

}

điều này có thể được sử dụng như hình dưới đây:

var createVector = overload(
        function (length) {
            return { x: length / 1.414, y: length / 1.414 };
        },
        function (a, b) {
            return { x: a, y: b };
        },
        function (a, b,c) {
            return { x: a, y: b, z:c};
        }
    );
console.log(createVector(3, 4));
console.log(createVector(3, 4,5));
console.log(createVector(7.07));

Giải pháp này không hoàn hảo nhưng tôi chỉ muốn chứng minh làm thế nào nó có thể được thực hiện.


2

Bạn có thể sử dụng 'addMethod' từ John Resig. Với phương pháp này, bạn có thể "quá tải" các phương thức dựa trên số lượng đối số.

// addMethod - By John Resig (MIT Licensed)
function addMethod(object, name, fn){
    var old = object[ name ];
    object[ name ] = function(){
        if ( fn.length == arguments.length )
            return fn.apply( this, arguments );
        else if ( typeof old == 'function' )
            return old.apply( this, arguments );
    };
}

Tôi cũng đã tạo ra một phương án thay thế cho phương thức này sử dụng bộ nhớ đệm để giữ các biến thể của hàm. Sự khác biệt được mô tả ở đây

// addMethod - By Stavros Ioannidis
function addMethod(obj, name, fn) {
  obj[name] = obj[name] || function() {
    // get the cached method with arguments.length arguments
    var method = obj[name].cache[arguments.length];

    // if method exists call it 
    if ( !! method)
      return method.apply(this, arguments);
    else throw new Error("Wrong number of arguments");
  };

  // initialize obj[name].cache
  obj[name].cache = obj[name].cache || {};

  // Check if a method with the same number of arguments exists  
  if ( !! obj[name].cache[fn.length])
    throw new Error("Cannot define multiple '" + name +
      "' methods with the same number of arguments!");

  // cache the method with fn.length arguments
  obj[name].cache[fn.length] = function() {
    return fn.apply(this, arguments);
  };
}

2

Mẫu chuyển tiếp => cách thực hành tốt nhất về nạp chồng JS

Chuyển tiếp đến một chức năng khác mà tên được xây dựng từ điểm thứ 3 và thứ 4:

  1. Sử dụng số lượng đối số
  2. Kiểm tra các loại đối số
window['foo_'+arguments.length+'_'+Array.from(arguments).map((arg)=>typeof arg).join('_')](...arguments)

Áp dụng cho trường hợp của bạn:

 function foo(){
          return window['foo_'+arguments.length+Array.from(arguments).map((arg)=>typeof arg).join('_')](...arguments);

  }
   //------Assuming that `x` , `y` and `z` are String when calling `foo` . 

  /**-- for :  foo(x)*/
  function foo_1_string(){
  }
  /**-- for : foo(x,y,z) ---*/
  function foo_3_string_string_string(){

  }

Mẫu phức tạp khác:

      function foo(){
          return window['foo_'+arguments.length+Array.from(arguments).map((arg)=>typeof arg).join('_')](...arguments);
       }

        /** one argument & this argument is string */
      function foo_1_string(){

      }
       //------------
       /** one argument & this argument is object */
      function foo_1_object(){

      }
      //----------
      /** two arguments & those arguments are both string */
      function foo_2_string_string(){

      }
       //--------
      /** Three arguments & those arguments are : id(number),name(string), callback(function) */
      function foo_3_number_string_function(){
                let args=arguments;
                  new Person(args[0],args[1]).onReady(args[3]);
      }

       //--- And so on ....   

2

Chức năng Quá tải thông qua Đa hình động trong 100 dòng JS

Đây là từ một cơ thể lớn hơn mã bao gồm isFn, isArrvv loại chức năng kiểm tra. Phiên bản VanillaJS dưới đây đã được làm lại để loại bỏ tất cả các phụ thuộc bên ngoài, tuy nhiên bạn sẽ phải xác định các chức năng kiểm tra loại của riêng bạn để sử dụng trong các .add()cuộc gọi.

Lưu ý: Đây là một chức năng tự thực hiện (vì vậy chúng ta có thể có một phạm vi đóng / đóng), do đó việc gán cho window.overloadthay vì function overload() {...}.

window.overload = function () {
    "use strict"

    var a_fnOverloads = [],
        _Object_prototype_toString = Object.prototype.toString
    ;

    function isFn(f) {
        return (_Object_prototype_toString.call(f) === '[object Function]');
    } //# isFn

    function isObj(o) {
        return !!(o && o === Object(o));
    } //# isObj

    function isArr(a) {
        return (_Object_prototype_toString.call(a) === '[object Array]');
    } //# isArr

    function mkArr(a) {
        return Array.prototype.slice.call(a);
    } //# mkArr

    function fnCall(fn, vContext, vArguments) {
        //# <ES5 Support for array-like objects
        //#     See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply#Browser_compatibility
        vArguments = (isArr(vArguments) ? vArguments : mkArr(vArguments));

        if (isFn(fn)) {
            return fn.apply(vContext || this, vArguments);
        }
    } //# fnCall

    //# 
    function registerAlias(fnOverload, fn, sAlias) {
        //# 
        if (sAlias && !fnOverload[sAlias]) {
            fnOverload[sAlias] = fn;
        }
    } //# registerAlias

    //# 
    function overload(vOptions) {
        var oData = (isFn(vOptions) ?
                { default: vOptions } :
                (isObj(vOptions) ?
                    vOptions :
                    {
                        default: function (/*arguments*/) {
                            throw "Overload not found for arguments: [" + mkArr(arguments) + "]";
                        }
                    }
                )
            ),
            fnOverload = function (/*arguments*/) {
                var oEntry, i, j,
                    a = arguments,
                    oArgumentTests = oData[a.length] || []
                ;

                //# Traverse the oArgumentTests for the number of passed a(rguments), defaulting the oEntry at the beginning of each loop
                for (i = 0; i < oArgumentTests.length; i++) {
                    oEntry = oArgumentTests[i];

                    //# Traverse the passed a(rguments), if a .test for the current oArgumentTests fails, reset oEntry and fall from the a(rgument)s loop
                    for (j = 0; j < a.length; j++) {
                        if (!oArgumentTests[i].tests[j](a[j])) {
                            oEntry = undefined;
                            break;
                        }
                    }

                    //# If all of the a(rgument)s passed the .tests we found our oEntry, so break from the oArgumentTests loop
                    if (oEntry) {
                        break;
                    }
                }

                //# If we found our oEntry above, .fn.call its .fn
                if (oEntry) {
                    oEntry.calls++;
                    return fnCall(oEntry.fn, this, a);
                }
                //# Else we were unable to find a matching oArgumentTests oEntry, so .fn.call our .default
                else {
                    return fnCall(oData.default, this, a);
                }
            } //# fnOverload
        ;

        //# 
        fnOverload.add = function (fn, a_vArgumentTests, sAlias) {
            var i,
                bValid = isFn(fn),
                iLen = (isArr(a_vArgumentTests) ? a_vArgumentTests.length : 0)
            ;

            //# 
            if (bValid) {
                //# Traverse the a_vArgumentTests, processinge each to ensure they are functions (or references to )
                for (i = 0; i < iLen; i++) {
                    if (!isFn(a_vArgumentTests[i])) {
                        bValid = _false;
                    }
                }
            }

            //# If the a_vArgumentTests are bValid, set the info into oData under the a_vArgumentTests's iLen
            if (bValid) {
                oData[iLen] = oData[iLen] || [];
                oData[iLen].push({
                    fn: fn,
                    tests: a_vArgumentTests,
                    calls: 0
                });

                //# 
                registerAlias(fnOverload, fn, sAlias);

                return fnOverload;
            }
            //# Else one of the passed arguments was not bValid, so throw the error
            else {
                throw "poly.overload: All tests must be functions or strings referencing `is.*`.";
            }
        }; //# overload*.add

        //# 
        fnOverload.list = function (iArgumentCount) {
            return (arguments.length > 0 ? oData[iArgumentCount] || [] : oData);
        }; //# overload*.list

        //# 
        a_fnOverloads.push(fnOverload);
        registerAlias(fnOverload, oData.default, "default");

        return fnOverload;
    } //# overload

    //# 
    overload.is = function (fnTarget) {
        return (a_fnOverloads.indexOf(fnTarget) > -1);
    } //# overload.is

    return overload;
}();

Sử dụng:

Người gọi xác định các hàm quá tải của chúng bằng cách gán một biến cho trả về overload(). Nhờ có chuỗi, quá tải bổ sung có thể được xác định theo chuỗi:

var myOverloadedFn = overload(function(){ console.log("default", arguments) })
    .add(function(){ console.log("noArgs", arguments) }, [], "noArgs")
    .add(function(){ console.log("str", arguments) }, [function(s){ return typeof s === 'string' }], "str")
;

Đối số tùy chọn duy nhất để overload()xác định hàm "mặc định" để gọi nếu chữ ký không thể được xác định. Các đối số .add()là:

  1. fn: functionxác định quá tải;
  2. a_vArgumentTests: Arraycủa functions xác định các bài kiểm tra để chạy trên arguments. Mỗi đối tượng functionchấp nhận một đối số duy nhất và trả về truethy dựa trên nếu đối số đó hợp lệ;
  3. sAlias(Tùy chọn): stringxác định bí danh để truy cập trực tiếp vào hàm quá tải ( fn), ví dụ: myOverloadedFn.noArgs()sẽ gọi hàm đó trực tiếp, tránh các phép thử đa hình động của các đối số.

Việc triển khai này thực sự cho phép nhiều hơn chỉ là quá tải chức năng truyền thống như là a_vArgumentTestsđối số thứ hai .add()trong thực tế xác định các loại tùy chỉnh. Vì vậy, bạn có thể cổng đối số không chỉ dựa trên loại, mà dựa trên phạm vi, giá trị hoặc bộ sưu tập giá trị!

Nếu bạn xem qua 145 dòng mã, overload()bạn sẽ thấy rằng mỗi chữ ký được phân loại theo số lượng argumentsđược chuyển cho nó. Điều này được thực hiện để chúng tôi giới hạn số lượng thử nghiệm chúng tôi đang chạy. Tôi cũng theo dõi số lượng cuộc gọi. Với một số mã bổ sung, các mảng của các hàm quá tải có thể được sắp xếp lại để các hàm được gọi phổ biến hơn được kiểm tra trước, thêm một số biện pháp nâng cao hiệu suất.

Bây giờ, có một số hãy cẩn thận ... Như Javascript là loại lỏng lẻo, bạn sẽ phải cẩn thận với bạn vArgumentTestsnhư một integerthể xác nhận như một floatvv

Phiên bản JSCompress.com (1114 byte, 744 byte g-zip):

window.overload=function(){'use strict';function b(n){return'[object Function]'===m.call(n)}function c(n){return!!(n&&n===Object(n))}function d(n){return'[object Array]'===m.call(n)}function e(n){return Array.prototype.slice.call(n)}function g(n,p,q){if(q=d(q)?q:e(q),b(n))return n.apply(p||this,q)}function h(n,p,q){q&&!n[q]&&(n[q]=p)}function k(n){var p=b(n)?{default:n}:c(n)?n:{default:function(){throw'Overload not found for arguments: ['+e(arguments)+']'}},q=function(){var r,s,t,u=arguments,v=p[u.length]||[];for(s=0;s<v.length;s++){for(r=v[s],t=0;t<u.length;t++)if(!v[s].tests[t](u[t])){r=void 0;break}if(r)break}return r?(r.calls++,g(r.fn,this,u)):g(p.default,this,u)};return q.add=function(r,s,t){var u,v=b(r),w=d(s)?s.length:0;if(v)for(u=0;u<w;u++)b(s[u])||(v=_false);if(v)return p[w]=p[w]||[],p[w].push({fn:r,tests:s,calls:0}),h(q,r,t),q;throw'poly.overload: All tests must be functions or strings referencing `is.*`.'},q.list=function(r){return 0<arguments.length?p[r]||[]:p},l.push(q),h(q,p.default,'default'),q}var l=[],m=Object.prototype.toString;return k.is=function(n){return-1<l.indexOf(n)},k}();

2

Bây giờ bạn có thể thực hiện nạp chồng hàm trong ECMAScript 2018 mà không cần polyfill, kiểm tra độ dài / loại var, v.v., chỉ cần sử dụng cú pháp lây lan .

function foo(var1, var2, opts){
  // set default values for parameters
  const defaultOpts = {
    a: [1,2,3],
    b: true,
    c: 0.3289,
    d: "str",
  }
  // merge default and passed-in parameters
  // defaultOpts must go first!
  const mergedOpts = {...defaultOpts, ...opts};

  // you can now refer to parameters like b as mergedOpts.b,
  // or just assign mergedOpts.b to b
  console.log(mergedOpts.a);
  console.log(mergedOpts.b);
  console.log(mergedOpts.c);  
  console.log(mergedOpts.d);
}
// the parameters you passed in override the default ones
// all JS types are supported: primitives, objects, arrays, functions, etc.
let var1, var2="random var";
foo(var1, var2, {a: [1,2], d: "differentString"});

// parameter values inside foo:
//a: [1,2]
//b: true
//c: 0.3289
//d: "differentString"

Cú pháp lây lan là gì?

Thuộc tính Rest / Spread cho đề xuất ECMAScript (giai đoạn 4) thêm thuộc tính trải rộng cho các đối tượng bằng chữ. Nó sao chép các thuộc tính vô số của riêng mình từ một đối tượng được cung cấp lên một đối tượng mới. Thêm về md

Lưu ý: cú pháp lây lan trong các đối tượng bằng chữ không hoạt động trong Edge và IE và đó là một tính năng thử nghiệm. xem khả năng tương thích của trình duyệt


2

Một cái gì đó như thế này có thể được thực hiện cho quá tải chức năng.

function addCSS(el, prop, val) {
  return {
    2: function() {
      // when two arguments are set
      // now prop is an oject
      for (var i in prop) {
          el.style[i] = prop[i];
      }
    },
    3: function() {
      // when three arguments are set
      el.style[prop] = val;
    }
    }[arguments.length]();
}
// usage
var el = document.getElementById("demo");
addCSS(el, "color", "blue");
addCSS(el, {
    "backgroundColor": "black",
  "padding": "10px"
});

Nguồn


1

Đây là một câu hỏi cũ nhưng một câu hỏi mà tôi nghĩ cần một mục khác (mặc dù tôi nghi ngờ bất cứ ai sẽ đọc nó). Việc sử dụng Biểu thức hàm được gọi ngay lập tức (IIFE) có thể được sử dụng cùng với các bao đóng và các hàm nội tuyến để cho phép nạp chồng hàm. Hãy xem xét ví dụ (giả định) sau đây:

var foo;

// original 'foo' definition
foo = function(a) {
  console.log("a: " + a);
}

// define 'foo' to accept two arguments
foo = (function() {
  // store a reference to the previous definition of 'foo'
  var old = foo;

  // use inline function so that you can refer to it internally
  return function newFoo(a,b) {

    // check that the arguments.length == the number of arguments 
    // defined for 'newFoo'
    if (arguments.length == newFoo.length) {
      console.log("a: " + a);
      console.log("b: " + b);

    // else if 'old' is a function, apply it to the arguments
    } else if (({}).toString.call(old) === '[object Function]') {
      old.apply(null, arguments);
    }
  }
})();

foo(1);
> a: 1
foo(1,2);
> a: 1
> b: 2
foo(1,2,3)
> a: 1

Nói tóm lại, việc sử dụng IIFE tạo ra một phạm vi cục bộ, cho phép chúng ta xác định biến riêng oldđể lưu trữ một tham chiếu đến định nghĩa ban đầu của hàm foo. Hàm này sau đó trả về một hàm nội tuyến newFooghi lại nội dung của cả hai đối số nếu nó được truyền chính xác hai đối số abhoặc gọi oldhàm if arguments.length !== 2. Mẫu này có thể được lặp lại bất kỳ số lần nào để cung cấp cho một biến với một số sai lệch chức năng khác nhau.


1

Tôi muốn chia sẻ một ví dụ hữu ích về cách tiếp cận giống như quá tải.

function Clear(control)
{
  var o = typeof control !== "undefined" ? control : document.body;
  var children = o.childNodes;
  while (o.childNodes.length > 0)
    o.removeChild(o.firstChild);
}

Cách sử dụng: Xóa (); // Xóa tất cả tài liệu

Xóa (myDiv); // Bảng điều khiển Clears được tham chiếu bởi myDiv


1

JavaScript là ngôn ngữ được đánh dấu và tôi chỉ nghĩ rằng điều đó hợp lý khi làm quá tải một phương thức / hàm liên quan đến số lượng tham số. Do đó, tôi khuyên bạn nên kiểm tra xem tham số đã được xác định chưa:

myFunction = function(a, b, c) {
     if (b === undefined && c === undefined ){
          // do x...
     }
     else {
          // do y...
     }
};

1
Chỉ muốn lưu ý rằng việc tháo gỡ không có nghĩa là "không có loại".
hamdiakoguz

1

Kể từ tháng 7 năm 2017, sau đây là kỹ thuật phổ biến. Lưu ý rằng chúng ta cũng có thể thực hiện kiểm tra kiểu trong hàm.

function f(...rest){   // rest is an array
   console.log(rest.length);
   for (v of rest) if (typeof(v)=="number")console.log(v);
}
f(1,2,3);  // 3 1 2 3

1

Đối với trường hợp sử dụng của bạn, đây là cách tôi sẽ giải quyết vấn đề này ES6(vì đã hết năm 2017):

const foo = (x, y, z) => {
  if (y && z) {
    // Do your foo(x, y, z); functionality
    return output;
  }
  // Do your foo(x); functionality
  return output;
}

Rõ ràng bạn có thể điều chỉnh điều này để làm việc với bất kỳ số lượng tham số nào và chỉ cần thay đổi các câu điều kiện phù hợp.


1

không có quá tải thực tế trong JS, dù sao chúng ta vẫn có thể mô phỏng quá tải phương thức theo nhiều cách:

phương pháp # 1: sử dụng đối tượng

function test(x,options){
  if("a" in options)doSomething();
  else if("b" in options)doSomethingElse();
}
test("ok",{a:1});
test("ok",{b:"string"});

phương pháp # 2: sử dụng các tham số rest (lây lan)

function test(x,...p){
 if(p[2])console.log("3 params passed"); //or if(typeof p[2]=="string")
else if (p[1])console.log("2 params passed");
else console.log("1 param passed");
}

phương pháp # 3: sử dụng không xác định

function test(x, y, z){
 if(typeof(z)=="undefined")doSomething();
}

phương pháp 4: kiểm tra kiểu

function test(x){
 if(typeof(x)=="string")console.log("a string passed")
 else ...
}

1

Mặc dù các tham số mặc định không quá tải, nhưng nó có thể giải quyết một số vấn đề mà các nhà phát triển gặp phải trong lĩnh vực này. Đầu vào được quyết định nghiêm ngặt theo đơn đặt hàng, bạn không thể đặt hàng lại theo ý muốn như trong quá tải cổ điển:

function transformer(
    firstNumber = 1,
    secondNumber = new Date().getFullYear(),
    transform = function multiply(firstNumber, secondNumber) {
        return firstNumber * secondNumber;
    }
) {
    return transform(firstNumber, secondNumber);
}

console.info(transformer());
console.info(transformer(8));
console.info(transformer(2, 6));
console.info(transformer(undefined, 65));

function add(firstNumber, secondNumber) {
    return firstNumber + secondNumber;
}
console.info(transformer(undefined, undefined, add));
console.info(transformer(3, undefined, add));

Kết quả trong (cho năm 2020):

2020
16160
12
65
2021
2023

Thông tin thêm: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Fiances/Default_parameter


0

Tùy chọn đầu tiên thực sự đáng được chú ý vì đó là điều tôi đã nghĩ ra trong thiết lập mã khá phức tạp. Vì vậy, câu trả lời của tôi là

  1. Sử dụng tên khác nhau ở nơi đầu tiên

Với một gợi ý nhỏ nhưng cần thiết, tên sẽ trông khác cho máy tính, nhưng không phải cho bạn. Tên các hàm quá tải như: func, func1, func2.


Tôi sẽ thử quá tải nhưng quyết định chỉ sử dụng các tên khác nhau, ví dụ getDeviceInfoByID và getDeviceInfoByType ...
CramerTV
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.