Home > Web Front-end > JS Tutorial > JavaScript uses encapsulation

JavaScript uses encapsulation

高洛峰
Release: 2016-11-30 16:59:45
Original
992 people have browsed it

Basic encapsulation method

Please see the following example:

var Person = function(name,age){
  this.name = name;
  this.age = age || "未填写";
  this.hobbys = [];
}

Person.prototype = {
  sayName:function(){
    console.log(this.name);
  },
  sayAge:function(){
    console.log(this.age);
  },
  addHobby:function(hobbys){
    this.hobbys = this.hobbys.concat(hobbys);
  }
}

var person1 = new Person("Jane","20");
var person2 = new Person("TabWeng","21");

person1.addHobby(['sing','drawing']);
person2.addHobby(['football','study','running']);

person1.sayName();
console.log(person1.hobbys.toString());

person2.sayName();
console.log(person2.hobbys.toString());
Copy after login

Run result:

Jane
sing, drawing
TabWeng
football, study, running

This is mentioned in JavaScript creation object, the properties that can be shared are and methods are written on the prototype, and the properties and methods that require each instance to have its own copy are placed in the constructor.

Now there is a problem. The input name cannot contain numbers. How to solve it? The solution is to write a function that checks the name and write this function on the prototype.

var Person = function(name,age){
  //校验名称
  if(this.checkName(name)){
    throw new Error("名字 "+name+" 不能存在数字");
  }
  this.name = name;
  this.age = age || "未填写";
  this.hobbys = [];
}

Person.prototype = {
  //校验函数
  checkName:function(name){
    re = /\d/;
    return re.test(name);
  },
  sayName:function(){
    console.log(this.name);
  },
  sayAge:function(){
    console.log(this.age);
  },
  addHobby:function(hobbys){
    this.hobbys = this.hobbys.concat(hobbys);
  }
}

var person1 = new Person("Helen666","20");
var person2 = new Person("TabWeng","21");

person1.addHobby(['sing','drawing']);
person2.addHobby(['football','study','running']);

person1.sayName();
console.log(person1.hobbys.toString());

person2.sayName();
console.log(person2.hobbys.toString());
Copy after login

In this code, we wrote a checkName() function to verify the name. For the time being, we just want to verify that there cannot be numbers. Then we will verify it in the first line of code in the constructor. If the verification fails, If passed, an exception is thrown.
Here I passed in a name Helen666, and the following exception was thrown:

Error: The name Helen666 cannot contain numbers

This achieves a basic encapsulation and implements internal verification.

But there is another problem. We can also define the name like this:

var person1 = new Person("Helen","20");
person1.name = "Helen666";
person1.sayName(); //Helen666
Copy after login

The name can still be modified to an illegal name, so we thought of using the get method and the set method for control, and the value can only be assigned through the set method , while verifying through the set method, and obtaining the value through the get method. The current code modification is as follows:

// Interfacevar People = new Interface("People",["setName","getName","setAge","getAge","addHobby","getHobby","sayName","sayAge"]);var Person = function(name,age){ //implement People
  this.setName(name);
  this.setAge(age);
  this._hobbys = [];}Person.prototype = {
  //校验函数
  checkName:function(name){
    re = /\d/;
    return re.test(name);
  },
  sayName:function(){
    console.log(this._name);
  },
  sayAge:function(){
    console.log(this._age);
  },
  addHobby:function(hobbys){
    this._hobbys = this._hobbys.concat(hobbys);
  },
  getHobby:function(){
    return this._hobbys;
  },
  setName:function(name){
    if(this.checkName(name)){
      throw new Error("名字 "+name+" 不能含有数字");
    }
    this._name = name;
  },
  getName:function(){
    return this._name;
  },
  setAge:function(age){
    this._age = age || "未设置"; 
  },
  getAge:function(){
    return this._age;
  }}var person1 = new Person("Helen","20");person1.addHobby(['sing','drawing']);function record(person){
  Interface.ensureImplements(person,People);
  person.sayName();
  console.log(person.getHobby().toString());}record(person1);
Copy after login

Running results:

Helen
sing, drawing

First of all, in this code we use an interface and define the People interface, and person implements this interface. Pay attention to the content of the comments. (For interfaces, please see this article JavaScript uses interfaces)
Secondly, we use the get method and the set method to obtain and assign values. We can agree that programmers can only assign values ​​through set, and in the set method we assign values The values ​​are checked to ensure accuracy. But this is just a convention. Programmers can still assign values ​​and modify internal attributes through person1.name = "123".
In order to standardize and serve as a reminder, we standardize the naming of internal attributes and add "_" in front of these attributes, such as **_name** and **_age**, so that if the programmer wants to modify the attributes directly, Then he must write person1._name = "123" like this. This is obviously a deliberate approach. Most programmers will not do this, and it serves as a standard and reminder.

Despite this, this kind of restriction only by regulations cannot prevent modification through person1._name. The following method can truly privatize the internal attributes.

Encapsulation through closure

// Interface
var People = new Interface("People",["setName","getName","setAge","getAge","addHobby","getHobby","sayName","sayAge"]);

var Person = function(name,age){ //implement People
  // 私有变量
  var _name,_age,_hobbys = [];

  this.addHobby = function(hobbys){
    _hobbys = _hobbys.concat(hobbys);
  },
  this.getHobby = function(){
    return _hobbys;
  },
  this.setName = function(name){
    if(this.checkName(name)){
      throw new Error("名字 "+name+" 不能含有数字");
    }
    _name = name;
  },
  this.getName = function(){
    return _name;
  },
  this.setAge = function(age){
    _age = age || "未设置"; 
  },
  this.getAge = function(){
    return _age;
  }

  this.setName(name);
  this.setAge(age);
}

Person.prototype = {
  checkName:function(name){
    re = /\d/;
    return re.test(name);
  },
  sayName:function(){
    console.log(this.getName());
  },
  sayAge:function(){
    console.log(this.getAge());
  }

}

var person1 = new Person("Helen","20");
person1.addHobby(['sing','drawing']);

function record(person){
  Interface.ensureImplements(person,People);
  person.sayName();
  console.log(person.getHobby().toString());
}

record(person1);
Copy after login

In the constructor, if the attribute does not use this, the attribute cannot be accessed externally, and the closure can access this attribute through the scope chain, then we set it through the closure The only entry point for assigning values ​​to attributes, thereby strictly verifying these attributes.

However, it is often unnecessary to define methods in the constructor, because every time an instance is created, a copy of the method will be generated, which requires memory support, so during use, if it can be used Use the above basic encapsulation method as much as possible. Unless there are very strict verification requirements for private attributes, use closure.


Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template