Edit: This is not a question about how prototype works. The problem was about code ordering. I have included the script below.
function copyPrototype(parent,descendant) {
var parentProto = Object.create(parent.prototype)
parentProto.constructor = descendant
descendant.prototype = parentProto
}
function addBird(_staysWinter) {
let bird = new Bird (_staysWinter)
return bird
}
function Bird(_staysWinter) {
Animal.call (this, 2)
this.staysWinter = _staysWinter
}
copyPrototype(Animal, Bird)
Bird.prototype.fly = function () {
alert ('flying')
}
function Animal (_numLegs) {
this.numLegs = _numLegs
}
Animal.prototype = {
walk: function () {
alert ('walking')
}
}
fluffy = addBird(0)
fluffy.fly()
fluffy.walk()
I am stuck...
Why does the following code snippet (jsfiddle) cause:
Uncaught TypeError: Cannot read property 'fly' of undefined
?
The idea here is that I have many different types of 'animals' (simplified) that all share certain properties. However I do not directly want to instantiate the underlying objects.
Essentially when I place an alert in prototype.fly to output this
, it returns undefined.
Begin of edit
In my example I took out the new
keyword, because I noticed the error in my own code as well (but instantiating bird did not fix it so I undid that change... hey i'm still learning).
The real problem was, as was only spotted by Berg, that I call animal before defining it and this was something I would not have found out using Google because I was under the impression that the order was irrelevant!
unfortunately my example was wrong, because I should have invoked bird.walk()
And that only works after reorganising my code.
I wrote a javascript merging tool that recursively browses my js classes and builds js files, that are then merged into main category js files that i can selectively include (bird.js, tiger.js, familytreeGrid.js, tetrisGrid.js etc).
At no point had I realised that the order was important until Bergi helped me out. So this is where the problem in my code comes from:
sequence.
Here is the javascript files merging script, for those interested.
#!/bin/bash
# assumes up-to-date version of Apache is used.
# searches for /js/includes/ dir in the currently enabled website, merges the files into a <directoyname>.js, per #<directoryname> under the main dir. Walks down into subdirs recursively, thus building up a .js file with all the required #subclasses in subdirectories. This allows for sharing generic classes, by placing them higher in the directory structure.
#Deepest directories names will become the javascript names.
# e.g. js/includes/animals.js
# js/includes/animals/birds.js
# js/includes/birds/sparrow.js
# js/inculdes/animals/insects/beetle.js
#will result in sparrow.js and beetle.js that both include animals.js, sparrow.js also has classes from birds.js
collectfromdir ()
{
local dir=$1
for subdir in $(ls -d ${dir}/*/ 2> /dev/null);do
collectfromdir "${subdir}"
done
if (( `ls ${dir}*.work 2> /dev/null|wc -l` ));then
find ${dir} -maxdepth 1 -type f -name "*.work"| while read collectedFile
do
(( `ls -l ${dir}*.js 2> /dev/null|wc -l` )) && cat ${dir}*.js >> ${dir}../`basename "$collectedFile"`
cat $collectedFile >> ${dir}../`basename $collectedFile`
rm $collectedFile
done
else
upDirFile=${dir%/}.work
#no workfile, create a file in parent dir with dirname
(( `ls -l ${dir}*.js 2> /dev/null|wc -l` )) && cat ${dir}*.js >> ./temp.work
(( `ls -l $upDirFile 2> /dev/null|wc -l` )) && cat $upDirFile >> ./temp.work
mv ./temp.work $upDirFile 2> /dev/null
fi
}
CURDIR=$(pwd)
mkdir -p $CURDIR/oldjsfiles
WEBPATH=`grep DocumentRoot /etc/apache2/sites-enabled/*.conf| cut -d ' ' -f2`
cd $WEBPATH/js/includes
for oldfile in $(ls *.js 2> /dev/null); do
mv $oldfile $CURDIR/oldjsfiles/${oldfile}.$(date +"%Y%m$d"_`date +"%H%M%S"`)
done
#recursive call
collectfromdir $WEBPATH/js/includes
find $WEBPATH/js/includes -maxdepth 1 -type f -name "*.work"| while read f
do
fnew=`basename $f .work`.js
mv $f $fnew
chmod 440 $fnew
done