下面的代码块包含一系列函数,这些函数涵盖了Javascript中的面向对象编程。它基于Youtuber的Derek Banas的第三个视频教程。
他从来没有完全完成他的.getStuff方法,但我一直试图通过方法重载和switch语句来完成。
显然,它之后的打印语句没有被执行,所以似乎有问题。我的代码出了什么问题?
此外,我还有一个普遍的问题,我如何在乐队网站上使用面向对象的编程?这些想法对游戏来说很好,但我看不出在普通网站上有什么用处(到目前为止,我已经学习了Pygame的OO编程,它对游戏设置来说完全有意义,但我知道在网站上的用途)。
这是我的代码,跳到底部获取.getStuff方法:
<!DOCTYPE html>
<html>
<head>
<title> Tutorial 3 (Object Orientated Programming) </title>
<meta http-equiv = "Content-Type" content = "text/html; charset = utf-8"/>
<script>
// This tutorial will cover OO based programming
// Object: Stores variables and the functions to manipulate these variables in one place
// Class: This is the blueprint that defines what variables and functions each object will
// have
// Property: Names given to variables stored inside of objects
// Methods: Name given to functions that are part of an object
// The following example will create an Animal object
// This is also called a constructor since it is a function that is designed to
// create (construct) a new object
function Animal()
{
// Define all the properties that you want the Animal object to contain:
// this: "This" is a reference to object that you create
this.name = "No Name";
this.sound = "Grrr";
this.owner = "No Owner";
}
// The following will create a prototype for a method that can be used by the Animal
// object
// Format is: nameOfObject.prototype.setOwner: this sets the value for the variable
// function(property that the function will accept)
// Encapsulation: Grouping of properties and their methods needed to manipulate
// those properties
Animal.prototype.setOwner = function(newOwner)
{
// The following checks if a newOwner value has been passed
if(typeof newOwner != 'undefined')
{
// You now want the value of owner to be the value of owner that has been
// passed to it as a parameter:
this.owner = newOwner;
}
else
{
document.write("Please enter a valid owner." + "</br>");
}
}
// This function will return whatever the name of the current owner is
Animal.prototype.getOwner = function()
{
return this.owner;
}
// Set the name of the animal using the previous method:
Animal.prototype.setName = function(newName)
{
if(typeof newName != 'undefined')
{
this.name = newName;
}
else
{
document.write("Please enter a valid name." + "</br>");
}
}
Animal.prototype.getName = function()
{
return this.name;
}
// Set the sound for the object:
Animal.prototype.setSound = function(newSound)
{
if(typeof newSound != 'undefined')
{
this.sound = newSound;
}
else
{
document.write("Please enter a valid sound." + "</br>");
}
}
Animal.prototype.getSound = function()
{
return this.sound;
}
// The following will literally create new Animal objects and probably call these
// function prototypes by passing in parameters for sound, name, and owner
var dog = new Animal();
// ^ This object has now been created and contains the defaults for sound, name, and owner
// according to the original function
// Now we are going to set the properties individually:
dog.setName("Cheyenne");
dog.setSound("Bark!");
dog.setOwner("Sam");
// Now, finally use the get versions of the functions by simply calling them via a document.write
document.write("The name of the dog is: " + dog.getName() + "</br>");
document.write("The sound of the dog is: " + dog.getSound() + "</br>");
document.write("The owner of the dog is: " + dog.getOwner() + "</br>");
// My small goal:
// Make a cat object instead:
var cat = new Animal();
cat.setName("Mr. Buttons")
cat.setSound("Purrrr")
cat.setOwner("Crazy Cat Lady")
// Print the results to screen:
document.write("The name of cat is: " + cat.getName() + "</br>");
document.write("The sound of the cat is: " + cat.getSound() + "</br>");
document.write("The owner of the cat is: " + cat.getOwner() + "</br>");
function Cat()
{
// The following will "inherit" all the attributes of the Animal class:
// This is a reference to the next cat object that you create.
// This forces the animal constructor to be called
Animal.call(this)
this.mood = "Crazy";
}
// Superclass: the class you want your new class to inherit from
// Without the following statement, Cat would become a subclass instead
Cat.prototype = new Animal();
// Here we are making the constructor be of type Cat
Cat.prototype.constructor = Cat();
// Create a getMood method:
Cat.prototype.getMood = function()
{
return this.mood;
}
// Create a setMOood method where the user passed in a mood as a parameter:
Cat.prototype.setMood = function(newMood)
{
if(typeof newMood != 'undefined')
{
this.mood = newMood;
}
else
{
document.write("Please enter a valid mood!</br>");
}
}
// Make a new Panda object:
function Panda()
{
Animal.call(this);
this.mood = "Calm";
}
Panda.prototype = new Animal();
Panda.prototype.constructor = Panda();
// Get Mood:
Panda.prototype.getMood = function()
{
return this.mood;
}
// Set Mood:
Panda.prototype.setMood = function(newMood)
{
if(typeof newMood != 'undefined')
{
this.mood = newMood;
}
else
{
document.write("Please enter a valid mood!</br>");
}
}
myPanda = new Panda();
myPanda.setMood("Excited");
document.write("myPanda's mood is: " + myPanda.getMood() + "</br>");
theGreatOne = new Panda();
theGreatOne.setMood("Courageous");
document.write("theGreatOne's mood is: " + theGreatOne.getMood() + "</br>");
// The following will determine if myPanda is an INSTANCE of the Panda class or
// an actual Panda object:
document.write("Is myPanda an instance of the Panda class?: " + (myPanda instanceof Panda) + "</br>");
// The following will use "typeof" to determine the data type of the myPanda object
// and the Panda class
// As seen by the example, classes are classified as functions in Javascripts
document.write("What is the data type of myPanda?: " + (typeof myPanda) + "</br>");
document.write("What is the data type of Panda?: " + (typeof Panda) + "</br>");
// Method Overloading: Creating multiple different versions or methods that all
// have a different number of attributes
// Aka, a different version of a method will be called depending on how many
// arguments are passed to the function
setStuff(newName);
setStuff(newName, newSound);
setStuff(newName, newSound, newOwner);
Panda.prototype.setStuff = function(newName, newSound, newOwner)
{
if((typeof newName != 'undefined') && (typeof newSound != 'undefined') && (typeof newOwner != 'undefined'))
{
Panda.prototype.setStuff = function(newName, newSound, newOwner)
{
switch(arguments.length)
{
case 3:
this.owner = newOwner;
case 2:
this.sound = newSound;
case 1:
this.name = newName;
}
}
}
else
{
document.write("Please enter a valid name</br>");
}
}
newPanda.setStuff("Jiggly");
document.write("myPanda's new name is: " + myPanda.getName() + "</br>");
// ^ Work on fixing this
// Continue at 15:51
// https://www.youtube.com/watch?v=xVnW7ZMqBus
// Polymorphism:
// doAnimalStuff(Animal){ document.write(Animal.getName() + Animal.getOwner()) };
</script>
<noscript>
</noscript>
</head>
<body>
<p> This is a sample paragraph </p>
</body>
</html>
Cat.prototype = new Animal();
不要这样做。更好:
Cat.prototype = Object.create(Animal.prototype);
document.write("The name of cat is: " + cat.getName() + "</br>");
尽量不要使用document.write
。对于这样的脚本示例,请改用console.log
。
// Method Overloading: Creating multiple different versions or methods that all // have a different number of attributes // Aka, a different version of a method will be called depending on how many // arguments are passed to the function setStuff(newName); setStuff(newName, newSound); setStuff(newName, newSound, newOwner);
这三行可能也应该出现在评论中。任何地方都没有定义setStuff
函数,因此尝试调用它将引发错误并停止脚本执行。检查错误控制台。更好:
// setStuff(newName);
// setStuff(newName, newSound);
// setStuff(newName, newSound, newOwner);
Cat.prototype.setMood = function(newMood) { … document.write("Please enter a valid mood!</br>"); }
OOP提示:尽量不要在setter方法中进行用户交互。这太具体了,并且假设a)用户调用了方法(而不是程序员)b)用户在某个地方输入了内容c)这种错误的首选输出方法是document.write
。这可能不是真的。
相反,做一个throw new Error("not a valid mood")
左右。如果它是用户可以输入的东西,那么在UI代码中捕获它,并在那里输出错误消息。它与猫没有任何关系。
Panda.prototype.setStuff = function(newName, newSound, newOwner) { if((typeof newName != 'undefined') && (typeof newSound != 'undefined') && (typeof newOwner != 'undefined')) { Panda.prototype.setStuff = function(newName, newSound, newOwner) {
什么?只声明(赋值)该方法一次!我没有完全检查,但似乎在右大括号处也有语法错误。
Cat.prototype.getMood = … Cat.prototype.setMood = … Panda.prototype.getMood = … Panda.prototype.setMood = …
不要重复你自己!可能的OOP解决方案包括:
- 在
Animal
类上定义情绪 - 引入一个新的子类
AnimalWithMood
是只有一些动物才能有情绪 - 如果希望任意类具有moods,请使用mixin模式
switch(arguments.length) { case 3: this.owner = newOwner; case 2: this.sound = newSound; case 1: this.name = newName; }
摔倒的有趣用法。然而,如果通过了4个论点,会发生什么,那么应该忽略它们吗?
一个明确的检查会更好:
if (arguments.length >= 3)
this.owner = newOwner;
if (arguments.length >= 2)
this.sound = newSound;
if (arguments.length >= 1)
// do validity checks in this block!
this.name = newName;
OOP提示:像setStuff
这样的God方法是被鄙视的——你可以在方法名称中看到它已经包含了"stuff"。考虑使用方法链接或对象作为参数的更流畅的接口。
我有一个普遍的问题,我如何在乐队网站上使用面向对象的编程?
太笼统了。OOP是一种编程范式,与代码的功能无关。此外,"XY网站"通常不需要任何编程。更具体地说,你想在你的页面上看到什么互动/动态的东西。