JavaScript: изменение функций по умолчанию с использованием подкласса? - PullRequest
0 голосов
/ 17 мая 2018

Я пытаюсь сделать простую игру с использованием JavaScript.Я хочу, чтобы каждый уровень в игре немного отличался.Тем не менее, я также хочу иметь поведение по умолчанию, так как не все части игры будут изменены.

Я подумал, что должен попытаться использовать подклассы и наследование, возможно, используя базу уровней, например:

"use strict";

function LevelBase() {
	this.load = function(level) {
		if (level === 1) {
			new Level1(this); // Can't do this = new Level1(this);
		}
	};
	this.func = function() {
		return 123;
	};
}

function Level1(game) {
	this.prototype = game;
	this.func = function() {
		return 456;
	};
}

var game = new LevelBase();
game.load(1);
console.log(game.func()); // Should print 456

Однако это не работает.Он по-прежнему использует поведение по умолчанию, и я чувствую, что это ужасный метод, который сделает все слишком сложным.Есть ли способ работы, чтобы сделать что-то вроде этого?

Любая помощь будет принята с благодарностью!

Ответы [ 3 ]

0 голосов
/ 17 мая 2018

Если вам не нужно поддерживать IE 11 или вы хотите его перенести, class - это удобный способ реализации наследования способом, аналогичным тому, как это делают языки на основе классов:

class LevelBase {
  load() {
    // ...
  }

  func() {
    return 123;
  }
}

class Level1 extends LevelBase {
  func() {
    return 456;
  }
}

const level = new Level1();
console.log(level.func()); // Prints 456

ИМО, это самый чистый способ наследования, и он должен хорошо работать, потому что он переводит на наследование на основе прототипов, которое является естественным для JavaScript.

0 голосов
/ 17 мая 2018

Вот подход, который будет работать в IE11 или любой другой среде ES5.

Он основан на нескольких служебных функциях для определения ваших классов, поддерживает одиночное наследование и перегрузку.Вы могли бы сохранить функции в меньшем скрипте, который загружается первым, или в верхней части вашего файла.

Что в основном основывалось на моем подходе, так это то, что мне нравятся любые решения, которые я использую, чтобы иметь чистый код, и эточто я придумал до «правильных» занятий в JS.

/*
	This function attaches a prototype object
	to a constructor function and returns it
	
	It also adds a super & base properties
	which can be used to infer which class an object came from (It's constructor function)
	
	e.g. var obj = new Class();
	
	Or using base on a class to check what it inherits from.
	
	Class.base = Base or Null if it has none
	
	obj.super = class;
*/
function _class(c,p) {
	p.base = null;
	p.super = c;
	c.prototype = p;
	
	return c;
}

/*
	This function takes a base class, constructor function and prototype object
	
	First the properties of the base prototype are iterated through,
	and any that aren't already on our new prototype are copied
	
	This essentially allows us to overload behaviour on the prototype by
	redefining it in decendants.
	
	Next a new constructor function is created that calls the base constructor first
	and then the derrived constructor afterward.
	
	function.apply() is a javascript function that can be applied to function objects
	in essense it's saying "Call this function as if you were a member of the first argument
	(the 'this' variable which would be the new object when the constructor is used) and
	use the same arguments that this outer function was called with".
	
	Another way to explain this is
	
	var obj = new nc(10);
		-> calls into nc with one argument '10'.
			-> That then calls into the base constructor with the same argument and 'this' set to the new object
			-> That then calls into the derrived constructor with the same argument and 'this' set to the new object
*/
_class.extends = function(b,c,p) {
	for (var pr in b.prototype) {
		if (!p[pr]) {
			p[pr] = b.prototype[pr];
		}
	}
	
	function nc() {
		b.apply(this,arguments);
		c.apply(this,arguments);
	}
	
	p.base = b;
	p.super = nc;
	nc.prototype = p;
	
	return nc;
}


var BaseClass = _class(
	// Base Constructor
	function(v1,v2) {
		this.v1 = v1;
		this.v2 = v2;
	},
	
	// Base prototype (Use for constants or class functions)
	{
		printValues: function() {
			console.log(
				this.v1,
				this.v2
			);
		}
	}
);

var DerrivedClass1 = _class.extends(BaseClass,
	function(v1,v2) {
		
	},
	
	{
		// It isn't defined here but this prototype contains the functions from the parent
	}
);

var DerrivedClass2 = _class.extends(BaseClass,
	function(v1,v2) {
		
	},
	
	{
		// This overloads inherited behaviour
		printValues: function() {
			console.log(
				"V1: " + this.v1,
				"V2: " + this.v2
			);
		}
	}
);

var obj_1 = new DerrivedClass1(10,20);
var obj_2 = new DerrivedClass2(30,40);

// This uses inherited behaviour
obj_1.printValues();

// This uses overloaded behaviour
obj_2.printValues();
0 голосов
/ 17 мая 2018

вы можете напрямую перегружать с помощью game.func = ....

"use strict";

function LevelBase() {
	this.load = function(level) {
		if (level === 1) {
			new Level1(this);
		}
	};
	this.func = function() {
		return 123;
	};
}

function Level1(game) {
	game.func = function() {
		return 456;
	};
}

var game = new LevelBase();
game.load(1);
console.log(game.func()); // Should print 456
...