JavaScript 中类的特性:
- 构造函数
- 静态属性,静态方法
- 共有属性,共有方法
- 私有属性,私有方法
一个简单的类
//Person():构造函数, Person:类var Person = function(name, age){//共有属性this.name = name;this.age = age;//共有方法this.sayName = function(){console.log(this.name);};
当对象被实例化后,构造函数会立即执行它所包含的任何代码
使用方式:
var p1 = new Person('zhuzhuxia',2);var p2 = Person('zhuzhuxia',2); //注意这里少了 newconsole.log(p1) //{name: "zhuzhuxia", age: 2, sayName: function}console.log(window.name); //undefinedconsole.log(window.age); //undefinedconsole.log(p2) //undefinedconsole.log(window.name); //zhuzhuxiaconsole.log(window.age); //2
Tip:
这里要说明下,使用 new 关键字,JavaScript会识别为对象,将 this 指向类的实例中,但是如果没有使用 new 关键字,this 将会指向全局变量 window,及 this.name = "zhuzhuxia" 等价于 window.name = "zhuzhuxia",因此 p2 是个无效值!
解决方案:
var Person = function(name, age){if (this instanceof Person){//共有属性this.name = name;this.age = age;//共有方法this.sayName = function(){console.log(this.name);};} else {return new Person(name, age);}}
效果:
var p1 = new Person('zhuzhuxia',2);var p2 = Person('zhuzhuxia',2); //注意这里少了 newconsole.log(p1) //{name: "zhuzhuxia", age: 2, sayName: function}console.log(window.name); //undefinedconsole.log(window.age); //undefinedconsole.log(p1) //{name: "zhuzhuxia", age: 2, sayName: function}console.log(window.name); //undefinedconsole.log(window.age); //undefined
一个复杂的类
有了上面的例子之后,我们在此基础之上就可以进行我们的完善了。
//全部在构造函数中创建的成员(注:只是以下形式定义的成员),将会在每个实例中生成同名的成员副本//因而实例越多占用的内存越多function Person(name, age) {//私有属性,不能被外部公开访问var defname = 'zhuzhuxia';//私有方法,不能被外部公开访问var sayName = function () {console.log(this.name);}function sayAge() {console.log(this.age);}//公有属性,可以被外部公开访问,且通过 实例 调用this.name = name;this.age = age;this.address = '中国';//公有方法,可以被外部公开访问,且通过 实例 调用this.say = function () {this.sayHello(defname); //在公有方法中可以访问私有成员和 prototype中的成员}}//公有属性,可以被外部公开访问,且通过 实例 调用//区别:prototype中添加成员,只有一份,与实例个数无关Person.prototype.sayHello = function (name) {if (name == undefined)console.log('Hello ' + this.name); //访问实例中的公有属性elseconsole.log('Hello ' + name);}//静态属性,可以被外部公开访问,但只能通过 构造函数 来调用Person.classname = '人';//静态方法,可以被外部公开访问,但只能通过 构造函数 来调用Person.showclass = function () {console.log(this.classname);}
实例化后使用:
//实例化var p = new Person('test');/*---- 测试prototype ----*/console.log(p.prototype); //undefined 实例对象没有prototypeconsole.log(Person.prototype); //{sayHello: ƒ, constructor: ƒ}console.log(Person.prototype.constructor); //Person(name,age){...} 构造函数整体,可以换做 alert来输出console.log(Person.prototype.constructor.classname); //china 相当于myObject.name;/*---- 测试属性 ----*/console.log(Person.address); //undefined Person中的this指的不是函数本身,而是调用address的对象,而且只能是对象console.log(Person.classname); //人console.log(p.address); //中国 此时this指的是实例化后的p,及p是调用address的对象console.log(p.classname); //undefined 静态属性不适用于一般实例console.log(p.constructor.classname); //人 想访问类的静态属性,先访问该实例的构造函数,然后在访问该类静态属性/*---- 测试方法 ----*/Person.showclass(); //人 直接调用 构造函数(类)的静态方法p.say(); //Hello zhuzhuxia Person类中的方法将会被实例继承p.sayHello(); //Hello test Person类的prototype原型下的方法将会被实例继承p.constructor.showclass();//人 调用该对象构造函数(类函数)的方法(函数)/*-- 错误的方法调用 --*///sayHello是原型方法,不是类的方法//Person.sayHello(); //Uncaught TypeError: Person.sayHello is not a function//showclass是Person类的方法,和实例对象没有直接关系//p.showclass(); //Uncaught TypeError: p.showclass is not a function
封装js类
这里我们用闭包来实现,首先解释下闭包的概念。
闭包概念:一个函数有权访问另一个函数作用域中的变量,即在一个函数内部创建另一个函数
实现如下:
var Person = (function(){//静态私有属性方法var home = "China";function sayHome(name){console.log(name + "'s home in " + home);}//构造函数function _person(name, age){var _this = this;//构造函数安全模式,避免创建时候丢掉new关键字if(_this instanceof _person){//共有属性, 方法_this.name = name;_this.getHome = function(){//内部访问私有属性,方法sayHome(_this.name);};_this.test = sayHome; //用于测试//构造器_this.setAge = function(age){_this.age = age + 12;}(age);}else{return new _person(name, age);}}//静态共有属性方法_person.prototype = {constructor: _person,drink: "water",sayWord: function(){console.log("ys is a boy");}}return _person;})();
调用如下:
var p1 = new Person("ys", 12);p1.getHome(); //ys's home in Chinaconsole.log(p1.age); //24var p2 = Person("ys", 12);p2.getHome(); //ys's home in Chinaconsole.log(p2.age); //24console.log(p2.test == p1.test); //true, 证明静态私有变量共享性
总结
- 有些公共属性,方法,可以设置为静态的,这样可以在每次实例化的时候,不需要额外开辟内存资源,达到真正意义上的共享,
- 有些公共的属性方法,只想在内部程序处理时候达到共享,则设置为,静态私有属性方法,
- 有些公共的属性方法,想在实例对象中达到共享,则设置为prototype属性方法

