Những kỹ thuật nào có thể được sử dụng để định nghĩa một lớp trong JavaScript và sự đánh đổi của chúng là gì?


686

Tôi thích sử dụng OOP trong các dự án quy mô lớn như dự án tôi đang làm. Tôi cần tạo một vài lớp trong JavaScript nhưng, nếu tôi không nhầm, có ít nhất một vài cách để thực hiện điều đó. Cú pháp là gì và tại sao nó lại được thực hiện theo cách đó?

Tôi muốn tránh sử dụng các thư viện của bên thứ ba - ít nhất là lúc đầu.
Tìm kiếm các câu trả lời khác, tôi tìm thấy bài viết Lập trình hướng đối tượng với JavaScript, Phần I: Kế thừa - Tài liệu JavaScript thảo luận về lập trình hướng đối tượng trong JavaScript. Có cách nào tốt hơn để làm thừa kế?


lưu ý: đây là bản sao của stackoverflow.com/questions/355848
Jason S

3
Cá nhân, tôi thích khai báo các thành viên lớp bên trong cơ thể chức năng. Tôi sử dụng kỹ thuật 'sửa lỗi này' để tạo sự đóng để làm cho nó hoạt động giống như một lớp hơn. Tôi đã có một ví dụ chi tiết trên blog của mình: ncombo.wordpress.com/2012/12/30/ Kẻ
Jon

Tôi đã chuyển hầu hết chức năng COP OOP sang JavaScript bằng một cú pháp đơn giản và tự nhiên. Xem câu trả lời của tôi ở đây: stackoverflow.com/a/18239463/1115652

Không có lớp trong JavaScript. Nhưng nếu bạn muốn mô phỏng hành vi giống nhau trong lớp, bạn có thể. Xem chi tiết trong: symfony-world.blogspot.com/2013/10/ trên
ducin

Câu trả lời:


743

Đây là cách để làm điều đó mà không cần sử dụng bất kỳ thư viện bên ngoài:

// Define a class like this
function Person(name, gender){

   // Add object properties like this
   this.name = name;
   this.gender = gender;
}

// Add methods like this.  All Person objects will be able to invoke this
Person.prototype.speak = function(){
    alert("Howdy, my name is" + this.name);
};

// Instantiate new objects with 'new'
var person = new Person("Bob", "M");

// Invoke methods like this
person.speak(); // alerts "Howdy, my name is Bob"

Bây giờ câu trả lời thực sự phức tạp hơn thế nhiều. Chẳng hạn, không có thứ gọi là lớp trong JavaScript. JavaScript sử dụng prototypesơ đồ thừa kế dựa trên cơ sở.

Ngoài ra, có rất nhiều thư viện JavaScript phổ biến có phong cách gần đúng với chức năng giống như lớp trong JavaScript. Bạn sẽ muốn kiểm tra ít nhất PrototypejQuery .

Quyết định cái nào trong số này là "tốt nhất" là một cách tuyệt vời để bắt đầu một cuộc chiến thần thánh trên Stack Overflow. Nếu bạn đang bắt tay vào một dự án nặng về JavaScript, chắc chắn bạn nên học một thư viện phổ biến và thực hiện theo cách của họ. Tôi là một anh chàng Prototype, nhưng Stack Overflow dường như nghiêng về jQuery.

Theo như chỉ có "một cách để làm điều đó", không có bất kỳ sự phụ thuộc nào vào các thư viện bên ngoài, thì cách tôi viết là khá nhiều.


48
Nhưng nó không hoạt động như ngôn ngữ X nơi tôi đã học được một cách chân thực rằng một thứ được sử dụng để tạo các đối tượng nên hoạt động :(
Erik Reppen

2
Theo developer.mozilla.org/en-US/docs/Web/JavaScript/, các thuộc tính cũng nên được thêm vào nguyên mẫu ("Person.prototype.name = '';")
DaveD

1
@DaveD - có thể nó đã làm, nhưng dường như không còn nữa ..?
Kieren Johnstone

6
jQuery thậm chí không cung cấp bất kỳ cách nào để tạo chức năng giống như lớp ??? (Tất cả các lớp mà nó có là các lớp CSS) Bạn nên xóa nó khỏi phần đó của câu trả lời.
Bergi

7
Từ nửa cuối năm 2015, tiêu chuẩn mới EcmaScript 6 đã được phát hành, vì vậy tôi đề xuất thực hiện theo cách mới (sạch hơn và dễ dàng hơn) es6-features.org/#ClassDefDef
DevWL

213

Cách tốt nhất để định nghĩa một lớp trong JavaScript là không định nghĩa một lớp.

Nghiêm túc.

Có một số hương vị khác nhau của hướng đối tượng, một số trong số đó là:

  • OO dựa trên lớp (được giới thiệu lần đầu bởi Smalltalk)
  • OO dựa trên nguyên mẫu (lần đầu tiên được giới thiệu bởi Self)
  • OO dựa trên multimethod (tôi nghĩ lần đầu tiên được giới thiệu bởi CommonLoops)
  • OO dựa trên vị ngữ (không có ý tưởng)

Và có lẽ những người khác tôi không biết.

JavaScript triển khai OO dựa trên nguyên mẫu. Trong OO dựa trên nguyên mẫu, các đối tượng mới được tạo bằng cách sao chép các đối tượng khác (thay vì được khởi tạo từ một mẫu lớp) và các phương thức sống trực tiếp trong các đối tượng thay vì trong các lớp. Việc kế thừa được thực hiện thông qua ủy quyền: nếu một đối tượng không có phương thức hoặc thuộc tính, thì nó được tra cứu trên (các) nguyên mẫu của nó (tức là đối tượng mà nó được nhân bản từ đó), sau đó các nguyên mẫu của nguyên mẫu, v.v.

Nói cách khác: không có lớp học.

JavaScript thực sự có một tinh chỉnh tốt của mô hình đó: các hàm tạo. Bạn không chỉ có thể tạo các đối tượng bằng cách sao chép các đối tượng hiện có, bạn cũng có thể xây dựng chúng "ngoài không khí mỏng", có thể nói như vậy. Nếu bạn gọi một hàm với newtừ khóa, hàm đó sẽ trở thành một hàm tạo và thistừ khóa sẽ không trỏ đến đối tượng hiện tại mà thay vào đó là một từ "trống" mới được tạo. Vì vậy, bạn có thể cấu hình một đối tượng theo bất kỳ cách nào bạn muốn. Theo cách đó, các hàm tạo JavaScript có thể đảm nhận một trong các vai trò của các lớp trong OO dựa trên lớp truyền thống: phục vụ như một khuôn mẫu hoặc bản thiết kế cho các đối tượng mới.

Bây giờ, JavaScript là một ngôn ngữ rất mạnh, vì vậy khá dễ dàng để triển khai hệ thống OO dựa trên lớp trong JavaScript nếu bạn muốn. Tuy nhiên, bạn chỉ nên làm điều này nếu bạn thực sự có nhu cầu và không chỉ vì đó là cách mà Java thực hiện.


"Nếu bạn gọi một hàm với từ khóa mới, hàm đó sẽ trở thành hàm tạo và từ khóa này sẽ không trỏ đến đối tượng hiện tại mà thay vào đó là một" rỗng "mới được tạo. Nếu bạn gọi một hàm mà không có từ khóa mới, thì điều này sẽ đề cập đến bối cảnh gọi, theo mặc định là đối tượng toàn cầu (cửa sổ). Trong chế độ nghiêm ngặt, không xác định là mặc định. gọi, áp dụng và liên kết lấy bối cảnh gọi làm tham số đầu tiên. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
Khăn

83

Lớp học ES2015

Trong đặc tả ES2015, bạn có thể sử dụng cú pháp lớp chỉ là đường trên hệ thống nguyên mẫu.

class Person {
  constructor(name) {
    this.name = name;
  }
  toString() {
    return `My name is ${ this.name }.`;
  }
}

class Employee extends Person {
  constructor(name, hours) {
    super(name);
    this.hours = hours;
  }
  toString() {
    return `${ super.toString() } I work ${ this.hours } hours.`;
  }
}

Những lợi ích

Lợi ích chính là các công cụ phân tích tĩnh tìm thấy mục tiêu cú pháp này dễ dàng hơn. Những người khác đến từ các ngôn ngữ dựa trên lớp cũng dễ dàng sử dụng ngôn ngữ này như một đa âm.

Hãy cẩn thận

Hãy cảnh giác với những hạn chế hiện tại của nó. Để đạt được các thuộc tính riêng tư, người ta phải sử dụng Biểu tượng hoặc WeakMaps . Trong các bản phát hành trong tương lai, các lớp rất có thể sẽ được mở rộng để bao gồm các tính năng còn thiếu này.

Ủng hộ

Hỗ trợ trình duyệt hiện tại không tốt lắm (được hỗ trợ bởi gần như tất cả mọi người trừ IE), nhưng bạn có thể sử dụng các tính năng này ngay bây giờ với một bộ chuyển mã như Babel .

Tài nguyên


56

Tôi thích sử dụng Daniel X. Moore {SUPER: SYSTEM}. Đây là một môn học cung cấp các lợi ích như các biến thể hiện thực, kế thừa dựa trên đặc điểm, phân cấp lớp và các tùy chọn cấu hình. Ví dụ dưới đây minh họa việc sử dụng các biến thể hiện thực, mà tôi tin là lợi thế lớn nhất. Nếu bạn không cần các biến thể hiện và chỉ hài lòng với các biến công khai hoặc riêng tư thì có lẽ có các hệ thống đơn giản hơn.

function Person(I) {
  I = I || {};

  Object.reverseMerge(I, {
    name: "McLovin",
    age: 25,
    homeState: "Hawaii"
  });

  return {
    introduce: function() {
      return "Hi I'm " + I.name + " and I'm " + I.age;
    }
  };
}

var fogel = Person({
  age: "old enough"
});
fogel.introduce(); // "Hi I'm McLovin and I'm old enough"

Ồ, điều đó thực sự không hữu ích lắm, nhưng hãy xem thêm một lớp con:

function Ninja(I) {
  I = I || {};

  Object.reverseMerge(I, {
    belt: "black"
  });

  // Ninja is a subclass of person
  return Object.extend(Person(I), {
    greetChallenger: function() {
      return "In all my " + I.age + " years as a ninja, I've never met a challenger as worthy as you...";
    }
  });
}

var resig = Ninja({name: "John Resig"});

resig.introduce(); // "Hi I'm John Resig and I'm 25"

Một lợi thế khác là khả năng có các mô-đun và tính kế thừa dựa trên đặc điểm.

// The Bindable module
function Bindable() {

  var eventCallbacks = {};

  return {
    bind: function(event, callback) {
      eventCallbacks[event] = eventCallbacks[event] || [];

      eventCallbacks[event].push(callback);
    },

    trigger: function(event) {
      var callbacks = eventCallbacks[event];

      if(callbacks && callbacks.length) {
        var self = this;
        callbacks.forEach(function(callback) {
          callback(self);
        });
      }
    },
  };
}

Một ví dụ về việc có lớp người bao gồm mô-đun ràng buộc.

function Person(I) {
  I = I || {};

  Object.reverseMerge(I, {
    name: "McLovin",
    age: 25,
    homeState: "Hawaii"
  });

  var self = {
    introduce: function() {
      return "Hi I'm " + I.name + " and I'm " + I.age;
    }
  };

  // Including the Bindable module
  Object.extend(self, Bindable());

  return self;
}

var person = Person();
person.bind("eat", function() {
  alert(person.introduce() + " and I'm eating!");
});

person.trigger("eat"); // Blasts the alert!

Tiết lộ: Tôi là Daniel X. Moore và đây là của tôi {SUPER: SYSTEM}. Đây là cách tốt nhất để định nghĩa một lớp trong JavaScript.


@DanielXMoore "Các biến sơ thẩm được chia sẻ giữa các cá thể của một lớp" Các biến đó không phải là các biến đối tượng, đó là các biến tĩnh / lớp.
JAB

2
@JAB Điều đó không chính xác, các biến tĩnh / lớp được chia sẻ giữa tất cả các phiên bản của một lớp. Mỗi trường hợp có các biến đối tượng riêng của nó.
Daniel X Moore

(Nói cách khác, bằng cách sử dụng ý nghĩa thông thường của thuật ngữ "instance variable", có hay không một biến là một là trực giao với mức độ khả năng tiếp cận của biến.)
JAB

2
Bạn gần như nghe như một siêu anh hùng khi tuyên bố xD hay nhất
Dadan

Một cách tiếp cận dễ dàng để xác định lớp Javascript bằng cách sử dụng các đối tượng javascript: wapgee.com/story/i/203
Ilyas karim

41
var Animal = function(options) {
    var name = options.name;
    var animal = {};

    animal.getName = function() {
        return name;
    };

    var somePrivateMethod = function() {

    };

    return animal;
};

// usage
var cat = Animal({name: 'tiger'});

Đây là một cách rất thanh lịch để xây dựng một cấu trúc đối tượng có thể sử dụng mà không phải nhập bất cứ thứ gì. Tôi đã sử dụng hệ thống lớp của Resig, nhưng tôi có thể thích điều này tốt hơn. Cảm ơn bạn.
Tim Scollick

29
Vấn đề với cách tiếp cận này là mỗi khi bạn tạo một cá thể Động vật mới, nó sẽ xác định lại các chức năng thay vì chỉ xác định chúng một lần với nguyên mẫu.
Justin

33

Sau đây là các cách tạo đối tượng trong javascript, mà tôi đã sử dụng cho đến nay

Ví dụ 1:

obj = new Object();
obj.name = 'test';
obj.sayHello = function() {
    console.log('Hello '+ this.name);
}

Ví dụ 2:

obj = {};
obj.name = 'test';
obj.sayHello = function() {
    console.log('Hello '+ this.name);
}
obj.sayHello();

Ví dụ 3:

var obj = function(nameParam) {
    this.name = nameParam;
}
obj.prototype.sayHello = function() {
    console.log('Hello '+ this.name);
}

Ví dụ 4: Lợi ích thực tế của Object.create (). vui lòng tham khảo [liên kết này]

var Obj = {
    init: function(nameParam) {
        this.name = nameParam;
    },
    sayHello: function() {
        console.log('Hello '+ this.name);
    }
};
var usrObj = Object.create(Obj);  // <== one level of inheritance

usrObj.init('Bob');
usrObj.sayHello();

Ví dụ 5 (Object.create tùy chỉnh của Crockford):

Object.build = function(o) {
   var initArgs = Array.prototype.slice.call(arguments,1)
   function F() {
      if((typeof o.init === 'function') && initArgs.length) {
         o.init.apply(this,initArgs)
      }
   }
   F.prototype = o
   return new F()
}
MY_GLOBAL = {i: 1, nextId: function(){return this.i++}}  // For example

var userB = {
    init: function(nameParam) {
        this.id = MY_GLOBAL.nextId();
        this.name = nameParam;
    },
    sayHello: function() {
        console.log('Hello '+ this.name);
    }
};
var bob = Object.build(userB, 'Bob');  // Different from your code
bob.sayHello();


Để giữ câu trả lời được cập nhật với ES6 / ES2015

Một lớp được định nghĩa như thế này:

class Person {
    constructor(strName, numAge) {
        this.name = strName;
        this.age = numAge;
    }

    toString() {
        return '((Class::Person) named ' + this.name + ' & of age ' + this.age + ')';
    }
}

let objPerson = new Person("Bob",33);
console.log(objPerson.toString());

1
@Justin: Xin vui lòng cho tôi biết những gì không hợp lệ?
Amol M Kulkarni

Trong khi nghiên cứu các ký hiệu này, tôi cũng tình cờ thấy this.set (). Ví dụ: this.set ('port', 3000). Tôi đoán là, điều này được sử dụng để đặt thuộc tính cổng cho đối tượng. Nếu vậy, tại sao chúng ta không trực tiếp sử dụng: {port: 3000}. Có tài liệu nào mà tôi có thể biết thêm chi tiết.
adityah

24

Tôi nghĩ bạn nên đọc Kế thừa nguyên mẫu của Douglas Crockford trong JavaScriptKế thừa cổ điển trong JavaScript .

Ví dụ từ trang của anh ấy:

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
};

Hiệu ứng? Nó sẽ cho phép bạn thêm các phương thức theo cách thanh lịch hơn:

function Parenizor(value) {
    this.setValue(value);
}

Parenizor.method('setValue', function (value) {
    this.value = value;
    return this;
});

Tôi cũng đề xuất các video của anh ấy: JavaScript nâng cao .

Bạn có thể tìm thấy nhiều video hơn trên trang của anh ấy: http://javascript.crockford.com/ Trong cuốn sách của John Reisig, bạn có thể tìm thấy nhiều ví dụ từ trang web của Douglas Crockfor.


25
Chỉ tôi thôi à? Làm thế quái nào là thanh lịch hơn? Tôi sẽ gọi các định nghĩa hàm với thực tế 'strings'là tên nhiều thứ, nhưng thanh lịch không phải là một trong số đó ...
fgysin phục hồi Monica

4
@JAB, nhưng phản ánh là ngoại lệ, không phải là quy tắc. Với phương thức trên, bạn phải khai báo tất cả các phương thức của bạn bằng chuỗi.
Kirk Woll

16

Bởi vì tôi sẽ không thừa nhận kế hoạch nhà máy của YUI / Crockford và vì tôi muốn giữ mọi thứ khép kín và có thể mở rộng nên đây là biến thể của tôi:

function Person(params)
{
  this.name = params.name || defaultnamevalue;
  this.role = params.role || defaultrolevalue;

  if(typeof(this.speak)=='undefined') //guarantees one time prototyping
  {
    Person.prototype.speak = function() {/* do whatever */};
  }
}

var Robert = new Person({name:'Bob'});

trong đó lý tưởng là kiểm tra typeof trên một cái gì đó giống như phương pháp đầu tiên được tạo mẫu


Tôi thích nó. Tôi thường sử dụng cú pháp tiêu chuẩn của JS vì tôi không thích ý tưởng sao chép các hàm vào từng thể hiện đối tượng. Tôi luôn bỏ lỡ vẻ đẹp của giải pháp khép kín, và điều này giải quyết nó khá tốt.
Lukasz Korzybski

1
Không chắc chắn nhưng tôi hiểu rằng việc xác định hàm nguyên mẫu bên trong phạm vi (phần nào là đóng) của hàm dẫn đến rò rỉ bộ nhớ do trình thu gom rác không thể đến đó trong trường hợp của các lớp đó.
Sanne

15

Nếu bạn đang đơn giản, bạn có thể tránh hoàn toàn từ khóa "mới" và chỉ sử dụng các phương thức xuất xưởng. Đôi khi tôi thích điều này, vì tôi thích sử dụng JSON để tạo các đối tượng.

function getSomeObj(var1, var2){
  var obj = {
     instancevar1: var1,
     instancevar2: var2,
     someMethod: function(param)
     {  
          //stuff; 
     }
  };
  return obj;
}

var myobj = getSomeObj("var1", "var2");
myobj.someMethod("bla");

Mặc dù vậy, tôi không chắc chắn hiệu năng đạt được là gì đối với các đối tượng lớn.


Dòng obj.instancevar1 = var1 là không cần thiết, vì đối tượng bên trong sẽ có quyền truy cập vào các tham số của getSomeObj ().
Triptych

Ồ Điều đó làm cho não của tôi bị tổn thương nhưng có một sự tao nhã nhất định với nó. Vì vậy, phần "obj.instancevar1 = var1" là khởi đầu của một loại hàm tạo, tôi cho rằng?
Karim

Chỉ cần thấy bình luận của Triptych. Tôi hiểu rồi. Vì vậy, bạn chỉ có thể làm một cái gì đó như "instancevar1: var1" trong đó đối tượng bên trong đang được khởi tạo.
Karim

Chính xác ... khi bạn sử dụng {} để xác định một đối tượng, nó có quyền truy cập vào các biến hiện đang ở trong phạm vi.
Sam

10
Với cách tiếp cận này, bạn mất khả năng kế thừa và vì bạn không sử dụng obj.prototype. Một cái gì đó bạn đang xác định các hàm mỗi khi bạn sử dụng đối tượng = nhiều bộ nhớ hơn và chậm hơn.
một số

12
var Student = (function () {
    function Student(firstname, lastname) {
        this.firstname = firstname;
        this.lastname = lastname;
        this.fullname = firstname + " " + lastname;
    }

    Student.prototype.sayMyName = function () {
        return this.fullname;
    };

    return Student;
}());

var user = new Student("Jane", "User");
var user_fullname = user.sayMyName();

Đó là cách TypeScript biên dịch lớp với hàm tạo thành JavaScript.


10

Cách đơn giản là:

function Foo(a) {
  var that=this;

  function privateMethod() { .. }

  // public methods
  that.add = function(b) {
    return a + b;
  };
  that.avg = function(b) {
    return that.add(b) / 2; // calling another public method
  };
}

var x = new Foo(10);
alert(x.add(2)); // 12
alert(x.avg(20)); // 15

Lý do thatthiscó thể bị ràng buộc với một cái gì đó khác nếu bạn đưa ra một phương thức như một trình xử lý sự kiện, vì vậy bạn lưu giá trị trong khi khởi tạo và sử dụng nó sau này.

Chỉnh sửa: đó chắc chắn không phải là cách tốt nhất, chỉ là một cách đơn giản. Tôi cũng đang chờ câu trả lời tốt!


1
Cấu trúc đó = không cần thiết ở đây. Ngoài ra, các phương thức add () và avg () sẽ được sao chép cho mọi "thể hiện" của lớp Foo, thay vì chia sẻ giữa chúng.
Triptych

1
Có cần thiết (sắp xếp) trong trường hợp đó không, nhưng không phải là trường hợp đơn giản bạn đã cung cấp.
Triptych

9

Bạn có thể muốn tạo một loại bằng cách sử dụng Mẫu gấp:

    // Here is the constructor section.
    var myType = function () {
        var N = {}, // Enclosed (private) members are here.
            X = this; // Exposed (public) members are here.

        (function ENCLOSED_FIELDS() {
            N.toggle = false;
            N.text = '';
        }());

        (function EXPOSED_FIELDS() {
            X.count = 0;
            X.numbers = [1, 2, 3];
        }());

        // The properties below have access to the enclosed fields.
        // Careful with functions exposed within the closure of the
        // constructor, each new instance will have it's own copy.
        (function EXPOSED_PROPERTIES_WITHIN_CONSTRUCTOR() {
            Object.defineProperty(X, 'toggle', {
                get: function () {
                    var before = N.toggle;
                    N.toggle = !N.toggle;
                    return before;
                }
            });

            Object.defineProperty(X, 'text', {
                get: function () {
                    return N.text;
                },
                set: function (value) {
                    N.text = value;
                }
            });
        }());
    };

    // Here is the prototype section.
    (function PROTOTYPE() {
        var P = myType.prototype;

        (function EXPOSED_PROPERTIES_WITHIN_PROTOTYPE() {
            Object.defineProperty(P, 'numberLength', {
                get: function () {
                    return this.numbers.length;
                }
            });
        }());

        (function EXPOSED_METHODS() {
            P.incrementNumbersByCount = function () {
                var i;
                for (i = 0; i < this.numbers.length; i++) {
                    this.numbers[i] += this.count;
                }
            };
            P.tweak = function () {
                if (this.toggle) {
                    this.count++;
                }
                this.text = 'tweaked';
            };
        }());
    }());

Mã đó sẽ cung cấp cho bạn một loại được gọi là myType . Nó sẽ có các trường riêng bên trong được gọi là chuyển đổivăn bản . Nó cũng sẽ có những thành viên tiếp xúc: các lĩnh vực đếmsố ; các thuộc tính chuyển đổi , văn bản và số Bước sóng ; các phương thức tăngNumbersByCountchỉnh .

Mẫu gấp được trình bày đầy đủ chi tiết tại đây: Mẫu gấp Javascript


3

Mã golf cho câu trả lời của @ liammclennan .

var Animal = function (args) {
  return {
    name: args.name,

    getName: function () {
      return this.name; // member access
    },

    callGetName: function () {
      return this.getName(); // method call
    }
  };
};

var cat = Animal({ name: 'tiger' });
console.log(cat.callGetName());


2

MooTools (Công cụ hướng đối tượng của tôi) tập trung vào ý tưởng của các lớp . Bạn thậm chí có thể mở rộng và thực hiện với sự kế thừa.

Khi thành thạo, nó làm cho javascript mạnh mẽ có thể tái sử dụng.


2

Các lớp học dựa trên đối tượng với sự kế thừa

var baseObject = 
{
     // Replication / Constructor function
     new : function(){
         return Object.create(this);   
     },

    aProperty : null,
    aMethod : function(param){
      alert("Heres your " + param + "!");
    },
}


newObject = baseObject.new();
newObject.aProperty = "Hello";

anotherObject = Object.create(baseObject); 
anotherObject.aProperty = "There";

console.log(newObject.aProperty) // "Hello"
console.log(anotherObject.aProperty) // "There"
console.log(baseObject.aProperty) // null

Đơn giản, ngọt ngào và được thực hiện.


1

Một căn cứ

function Base(kind) {
    this.kind = kind;
}

Một lớp học

// Shared var
var _greeting;

(function _init() {
    Class.prototype = new Base();
    Class.prototype.constructor = Class;
    Class.prototype.log = function() { _log.apply(this, arguments); }
    _greeting = "Good afternoon!";
})();

function Class(name, kind) {
    Base.call(this, kind);
    this.name = name;
}

// Shared function
function _log() {
    console.log(_greeting + " Me name is " + this.name + " and I'm a " + this.kind);
}

Hoạt động

var c = new Class("Joe", "Object");
c.log(); // "Good afternoon! Me name is Joe and I'm a Object"

1

Dựa trên ví dụ về Triptych, điều này thậm chí có thể đơn giản hơn:

    // Define a class and instantiate it
    var ThePerson = new function Person(name, gender) {
        // Add class data members
        this.name = name;
        this.gender = gender;
        // Add class methods
        this.hello = function () { alert('Hello, this is ' + this.name); }
    }("Bob", "M"); // this instantiates the 'new' object

    // Use the object
    ThePerson.hello(); // alerts "Hello, this is Bob"

Điều này chỉ tạo ra một thể hiện đối tượng duy nhất, nhưng vẫn hữu ích nếu bạn muốn gói gọn một loạt các tên cho biến và phương thức trong một lớp. Thông thường sẽ không có đối số "Bob, M" cho hàm tạo, ví dụ nếu các phương thức sẽ được gọi đến một hệ thống có dữ liệu riêng của nó, chẳng hạn như cơ sở dữ liệu hoặc mạng.

Tôi vẫn còn quá mới với JS để xem tại sao điều này không sử dụng prototypethứ này.


0

JavaScript hướng đối tượng , nhưng nó hoàn toàn khác so với các ngôn ngữ OOP khác như Java, C # hoặc C ++. Đừng cố hiểu nó như thế. Ném kiến ​​thức cũ ra và bắt đầu lại. JavaScript cần một suy nghĩ khác.

Tôi muốn đề nghị để có được một hướng dẫn tốt hoặc một cái gì đó về chủ đề này. Bản thân tôi thấy Hướng dẫn ExtJS là tốt nhất cho tôi, mặc dù tôi chưa sử dụng khung trước hoặc sau khi đọc nó. Nhưng nó đưa ra một lời giải thích tốt về những gì trong thế giới JavaScript. Xin lỗi, có vẻ như nội dung đó đã bị xóa. Đây là một liên kết đến archive.org sao chép . Hoạt động ngày hôm nay. : P


2
Hướng đối tượng? Tôi nghĩ rằng nó là chức năng .
Peter Mortensen

Liên kết "ExtJS Tutorials" bị hỏng.
Peter Mortensen

Tôi nghĩ sẽ có nhiều giải thích hơn để giải thích rằng các hàm trong javascript là các đối tượng và các quy tắc phạm vi khung của javascript làm cho mỗi khối chức năng được đóng gói.
mibbit

-1

//new way using this and new
function Persons(name) {
  this.name = name;
  this.greeting = function() {
    alert('Hi! I\'m ' + this.name + '.');
  };
}

var gee=new Persons("gee");
gee.greeting();

var gray=new Persons("gray");
gray.greeting();

//old way
function createPerson(name){
 var obj={};
 obj.name=name;
 obj.greeting = function(){
 console.log("hello I am"+obj.name);
 }; 
  return obj;
}

var gita=createPerson('Gita');
gita.greeting();

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.