本文最初发布于http://szhshp.org/tech/2017/02/18/JavaSprite.html
转载请注明
Prototype
Nearly all objects in JavaScript are instances of Object; a typical object inherits properties (including methods) from Object.prototype.
javascript中的对象类似一个指向prototype的指针和一个自身的属性列表
- prototype的修改将影响所有的对象
- 每个function都有一个默认的属性prototype,而这个prototype的constructor默认指向这个函数
Prototype 继承
可以给prototype添加方法或者属性
//create a class
function Person(name) {
this.name = name;
};
var p = new Person("Mike");
p.name;//Mike
//add a fun to prototype
Person.prototype.getName = function() {
return this.name;
};
p.getName();//Mike
console.log(Person.prototype.constructor === Person); // true
console.log(p.constructor === Person); // true, 'p' is inherited from the Person.prototype
同时注意,建立instance时是继承对应prototype,因此同名方法和属性会被重写
//create a class
function Person(name) {
debugger;
this.name = name; // the attr 'name' was overwritten here
};
Person.prototype.name = "Bill";
var p = new Person("Mike");
p.name;//Mike, the attr 'name' was overwritten
子类及原型继承
实现子类和原型继承的步骤:
- 继承prototype中定义的属性和方法;
- 继承构造函数中定义的属性和方法;
function Animal(name) {
this.name = name;
}
Animal.prototype.sex = "male";
Animal.prototype.info = function () {
console.log("animal");
}
// -------------------------------------------------------------
//Demo
var cat = new Animal('cat');
console.log(cat instanceof Animal); //t
console.log(cat instanceof Object); //t
console.log( typeof Animal.prototype); //object
console.log( typeof Animal.constructor); //function
console.log(Animal.prototype.constructor == Animal); //true
// -------------------------------------------------------------
// -------------------------------------------------------------
function People(name) {
this.name = name;
}
// prototype Is a obj, here we create an instance and assign to People.prototype
// in this way, we can inherit the attr and func from parent class
People.prototype = new Animal("animal");
// overwrite the func from parent class
People.prototype.info = function() {
console.log("people")
};
// -------------------------------------------------------------
//Demo2
var mike = new People("mike");
console.log(mike.sex);//male
mike.info();//People
console.log(mike instanceof People); //t
console.log(mike instanceof Animal); //t
console.log(mike instanceof Object); //t
console.log( typeof People.prototype); //object, its an instance of Animal
console.log( typeof People.constructor); //function
console.log(People.prototype.constructor == People); //true
JS的面向对象技术
封装
//create a class
function Person(name) {
this.name = Person.prefix + name;
this.firstName = Person.getFirstName(); // this is a function
};
Person.prefix = "Mc";// private variables
Person.getFirstName = function(){ // can't access from instants
return 'George';
}
var p = new Person("Mike");
p.name;//McMike
p.firstName();//George
Example
一个全面并且典型的纯OOP例子:
function Set() { // This is the constructor
this.values = {}; // The properties of this object hold the set
this.n = 0; // How many values are in the set
this.add.apply(this, arguments); // All arguments are values to add
}
// Add each of the arguments to the set.
Set.prototype.add = function () {
for (var i = 0; i < arguments.length; i++) { // For each argument
var val = arguments[i]; // The value to add to the set
var str = Set._v2s(val); // Transform it to a string
if (!this.values.hasOwnProperty(str)) { // If not already in the set
this.values[str] = val; // Map string to value
this.n++; // Increase set size
}
}
return this; // Support chained method calls
};
// Remove each of the arguments from the set.
Set.prototype.remove = function () {
for (var i = 0; i < arguments.length; i++) { // For each argument
var str = Set._v2s(arguments[i]); // Map to a string
if (this.values.hasOwnProperty(str)) { // If it is in the set
delete this.values[str]; // Delete it
this.n--; // Decrease set size
}
}
return this; // For method chaining
};
// Return true if the set contains value; false otherwise.
Set.prototype.contains = function (value) {
return this.values.hasOwnProperty(Set._v2s(value));
};
// Return the size of the set.
Set.prototype.size = function () {
return this.n;
};
// Call function f on the specified context for each element of the set.
Set.prototype.foreach = function (f, context) {
for (var s in this.values) // For each string in the set
if (this.values.hasOwnProperty(s)) // Ignore inherited properties
f.call(context, this.values[s]); // Call f on the value
};
Set._v2s = function (val) { //这是一个内部函数,当然实例对象无法调用这个方法
switch (val) {
case undefined:
return 'u'; // Special primitive
case null:
return 'n'; // values get single-letter
case true:
return 't'; // codes.
case false:
return 'f';
default:
switch (typeof val) {
case 'number':
return '#' + val; // Numbers get # prefix.
case 'string':
return '"' + val; // Strings get " prefix.
default:
return '@' + objectId(val); // Objs and funcs get @
}
}
// For any object, return a string. This function will return a different
// string for different objects, and will always return the same string
// if called multiple times for the same object. To do this it creates a
// property on o. In ES5 the property would be nonenumerable and read-only.
function objectId(o) {
var prop = "|**objectid**|"; // Private property name for storing ids
if (!o.hasOwnProperty(prop)) // If the object has no id
o[prop] = Set._v2s.next++; // Assign it the next available
return o[prop]; // Return the id
}
};
Set._v2s.next = 100; // Start assigning object ids at this value.
另一种通过返回值设定类的方法
function Test() {
var map = 1;
function a(){
map = 2;
}
function b(){
console.log(map);
}
return{
a:a,
b:b
}
}
var t = new Test()