JavaScript Rendering - javascript

Why doesn't this HTML/script (from "Secrets of the JavaScript Ninja") render?
http://jsfiddle.net/BCL54/
<html>
<head>
<script>
function outer(){
var a = 1;
function inner(){ /* does nothing */ }
var b = 2;
if (a == 1) {
var c = 3;
}
}
outer();
assert(true,"some descriptive text");
assert(typeof outer==='function',
"outer() is in scope");
assert(typeof inner==='function',
"inner() is in scope");
assert(typeof a==='number',
"a is in scope");
assert(typeof b==='number',
"b is in scope");
assert(typeof c==='number',
"c is in scope");
</script>
</head>
<body>
</body>
</html>

Because you didn't import Resig's necessary script containing the assert function :
<script>
function assert(pass, msg){
var type = pass ? "PASS" : "FAIL";
jQuery("#results").append("<li class='" + type + "'><b>" + type + "</b> " + msg + "</li>");
}
function error(msg){
jQuery("#results").append("<li class='ERROR'><b>ERROR</b> " + msg + "</li>");
}
function log(){
var msg = "";
for ( var i = 0; i < arguments.length; i++ ) {
msg += " " + arguments[i];
}
jQuery("#results").append("<li class='LOG'><b>LOG</b> " + msg + "</li>");
}
</script>
You can find those functions in the source of his site. Note that those function also ask for jQuery and some DOM elements into which to write. You'd better adapt to your page.
Until you're proficient enough in javascript to rewrite those functions, you'd better do the excellent exercises directly on the site.

Related

How can I create a function which treats a passed parameter as a literal?

I am sure that this has been asked and answered before, but I can't seem to find the right terminology to find an answer. I need to dynamically create a series of functions for later use which use certain values defined by parameters upon creation. For example:
var i = "bar";
var addBar = function(x) {
// needs to always return x + " " + "bar"
return x + " " + i;
}
i = "baz";
var addBaz = function(x) {
// needs to always return x + " " + "baz"
return x + " " + i;
}
alert(addBar("foo")); // returns "foo baz" because i = "baz"
Is there a way I can pass i to these functions so that the original value is used, and not the reference to the variable? Thank you!
You would have to do something that stores the variable. Making a function that returns a function is one way to do it.
var i = "bar";
var addBar = (function (i) {
return function(x) {
return x + " " + i;
}
}(i));
i = "baz";
var addBaz = (function (i) {
return function(x) {
return x + " " + i;
}
}(i));
console.log(addBar("foo"));
console.log(addBaz("foo"));

load obj and mtl file by three.js OBJMTLLoader.js causes memory leak after multi-times load

I get a memory leak when load several obj mesh with mtl file by three.js, here is my step:
First, open this page: http://idazhenhan.github.io/threejs/loader/index.html, after data loaded click 'load', you will see some yellow meshes on screen when you move your mouse slightly;
Then, if you use windows, just open you task manager, see how much memory the browser tab cost, record it.
Last, click 'reload' re-click 'load' or 'clear' on top-left of the page, watch the memory cost in task manager again, you will see, the memory is growing up and/or seemed will never free.
I write some release code at the end of the index.js, here it is:
function reload() {
var indexes = [];
for (var index in scene.children) {
if(scene.children[index].name.indexOf('test') !== -1){
indexes.push(scene.children[index]);
}
}
for(var index in indexes){
scene.remove(indexes[index]);
}
load();
};
I have change the two main functions:
function load() {
clear();
var paths = [];
for(var i=1;i<=4;i++){
paths.push({obj: i + '/model_1v.obj', mtl: i + '/model_1v.mtl'});
}
var onProgress = function(xhr) {
if (xhr.lengthComputable) {
var percentComplete = xhr.loaded / xhr.total * 100;
}
};
var onError = function(xhr) {};
THREE.Loader.Handlers.add(/\.dds$/i, new THREE.DDSLoader());
for(var i=0;i<paths.length;i++){
var path = paths[i];
var loader = new THREE.OBJMTLLoader();
loader.load(path.obj, path.mtl, function(model) {
model.name='test-' + i;
scene.add(model);
}, onProgress, onError);
}
}
function clear() {
THREE.Cache.clear();
var models = [];
for (var i in scene.children) {
if(scene.children[i].name.indexOf('test') !== -1){
models.push(scene.children[i]);
}
}
for(var i in models){
scene.remove(models[i]);
models[i].traverse(
function(obj){
if (obj instanceof THREE.Mesh) {
obj.geometry.dispose();
obj.material.dispose();
}
}, true
);
}
models.length = 0;
};
But it is still invalid, if you are interested of this, you can clone the code at here : https://github.com/idazhenhan/idazhenhan.github.io.git , then run the code on you local server, you will see the problem clearly.
Is there any one can help me to solve it?
For the javascript garbage collector (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management) to kick in all references to an object must be zero. One way to tell javascript that you are done with an object is to set it to undefined. In addition you need to dispose() all of the group of objects underneath. Here is my version of disposing a hierarchy.
After your call to scene.remove(models[i]);
Use it: disposeHierarchy (object, disposeNode); or disposeNode (node);
var debugging = false;
var indent = "", indent_level = 0;
function disposeNode (node)
{
if (debugging) console.log (indent_level + " " + indent + "\"" + node.name + "\"");
if (node instanceof THREE.Camera)
{
if (debugging) console.log (indent + "\"" + node.name + "\"" + " " + "\"" + node.type + "\"" + " Camera");
node = undefined;
}
else if (node instanceof THREE.Light)
{
if (debugging) console.log (indent + "\"" + node.name + "\"" + " " + "\"" + node.type + "\"" + " Light");
node.dispose ();
node = undefined;
}
else if (node instanceof THREE.Mesh)
{
if (debugging) console.log (indent + "\"" + node.name + "\"" + " " + "\"" + node.type + "\"" + " Mesh");
if (node.geometry)
{
if (debugging) console.log (indent + indent + "I have Geometry");
node.geometry.dispose ();
node.geometry = undefined;
}
if (node.material)
{
if (node.material instanceof THREE.MeshFaceMaterial)
{
if (debugging) console.log (indent + indent + "I have many Materials");
$.each (node.material.materials, function (idx, mtrl)
{
if (mtrl.map) mtrl.map.dispose ();
if (mtrl.lightMap) mtrl.lightMap.dispose ();
if (mtrl.bumpMap) mtrl.bumpMap.dispose ();
if (mtrl.normalMap) mtrl.normalMap.dispose ();
if (mtrl.specularMap) mtrl.specularMap.dispose ();
if (mtrl.envMap) mtrl.envMap.dispose ();
mtrl.dispose (); // disposes any programs associated with the material
mtrl = undefined;
});
}
else
{
if (debugging) console.log (indent + indent + "I have Material");
if (node.material.map) node.material.map.dispose ();
if (node.material.lightMap) node.material.lightMap.dispose ();
if (node.material.bumpMap) node.material.bumpMap.dispose ();
if (node.material.normalMap) node.material.normalMap.dispose ();
if (node.material.specularMap) node.material.specularMap.dispose ();
if (node.material.envMap) node.material.envMap.dispose ();
node.material.dispose (); // disposes any programs associated with the material
node.material = undefined;
}
}
node = undefined;
}
else if (node instanceof THREE.Object3D)
{
if (debugging) console.log (indent + "\"" + node.name + "\"" + " " + "\"" + node.type + "\"" + " Object3D");
node = undefined;
}
else
{
if (debugging) console.log (indent + "UNKNOWN " + "\"" + node.name + "\"" + " " + "\"" + typeof node + "\"");
}
}
function disposeHierarchy (node, callback)
{
indent += " ";
indent_level++;
for (var i = node.children.length - 1; i >= 0; i--)
{
var child = node.children[i];
disposeHierarchy (child, callback);
callback (child);
}
indent = indent.substr (4); // remove 4 spaces from indent
indent_level--;
}

What am I doing wrong?

This is my Javascript code I have so far. I am trying to create a personInfo() object with 2 functions. I am not sure what I am doing wrong.
var personInfo =
{
personInfo.personRelation: " ",
personInfo.personName: " ",
personInfo.personAge: 0,
personInfo.personGender: " "
var relationValue = personRelation;
var nameValue = personName;
var ageValue = personAge;
var genderValue = personGender;
getPersonInfo: function()
{
document.write( "<p>" + personInfo.personRelation + "<br />" );
document.write( "Name: " + personInfo.personName + "<br />");
document.write( "Age: " + personInfo.personAge + "<br />" );
document.write( "Gender: " + personInfo.personGender + "</p>" );
}
setPersonInfo(relationValue, nameValue, ageValue, genderValue): function()
{
this.relationValue = relationValue;
this.nameValue = nameValue;
this.ageValue = ageValue;
this.genderValue = genderValue;
}
}; // end object personInfo
This my html code...I am trying to print each object with the while loop. I am very new to Javascript, so I am not sure if I mistakes in the external javascript file or if it is simply my implementation. Any help would be great. Thank you.
<html>
<head>
<link rel="stylesheet" href="object.css" type ="text/css" />
<title>Object Test</title>
<script type="text/javascript" src="MyObject.js">
var people = new Array(5);
</script>
</head>
<body>
<script type="text/javascript" src="MyObject.js">
var dad_info = setPersonInfo("Dad", "Kenneth Vavrock", 66, "Male");
dad_info = people[0];
var mom_info = setPersonInfo("Mom", "Connie Vavrock", 63, "Female");
mom_info = people[1];
var brother_info = setPersonInfo("Brother", "Craig Vavrock", 33, "Male");
brother_info = people[2];
var nephew_info = setPersonInfo("Nephew", "Sawyer Vavrock", 1, "Male");
nephew_info = people[3];
var dad_info = setPersonInfo("Step Mother", "Bonnie Vavrock", 70, "Female");
stepmother_info = people[4];
var count = 1;
while ( count >= 0 )
{
dad_info.getPersonInfo();
mom_info.getPersonInfo();
brother_info.getPersonInfo();
nephew_info.getPersonInfo();
stepmother_info.getPersonInfo();
count--;
}
</script>
</body>
</html>
Your "personInfo" object is malformed, it looks like a mix between a object literal and a class-like function. Have a look at this tutorial
Also, do not use an empty string " " as default value for anything (unless you really need to), there is really no point to it.
To solve the problem at hand.
var personInfo = function () {
this.personRelation = "";
this.personName = "";
this.personAge = 0;
this.personGender = "";
this.getPersonInfo = function () {
document.write( "<p>" + personInfo.personRelation + "<br />" );
document.write( "Name: " + personInfo.personName + "<br />");
document.write( "Age: " + personInfo.personAge + "<br />" );
document.write( "Gender: " + personInfo.personGender + "</p>" );
}
};
This way it can be used as such:
var people = []; // Create an empty array
// Create new person info for "dad"
var dad_info = new personInfo();
dad_info.personRelation = "...";
// [...]
people.push(dad_info); // Add dad_info to the array.
You should be all set.

How can i get rid of putting "new" before a function

I was wondering how can I make it posible to get rid of putting "new" before a function, for example:
new functionToDo("thingsToDo").iGotYouBruh("Halo Humans");
is there a posible way of doing this without the "new"?
here is the code I'm trying to use without the "new":
function local (title) {
var storeTitle = title;
this.addL = function(lString) {
var storeText = lString;
localStorage.setItem(storeTitle, storeText);
console.info("Locally stored " + storeTitle.toUpperCase() + " with " + storeText.substring(0, 10) + "... As text.");
};
this.removeL = function() {
localStorage.removeItem(storeTitle);
console.info("Locally removed " + storeTitle + ".");
};
this.getL = function () {
localStorage.getItem(storeTitle);
console.info("Locally got string of " + storeTitle + ": " + localStorage.getItem(storeTitle));
};
};
and here's what I would have to do to invoke the function:
new local("storedElement").getL();
This is possible by checking whether this is an instance of the function itself and returning a new instance otherwise:
function local (title) {
if (!(this instanceof local)) {
return new local(title);
}
var storeTitle = title;
this.addL = function(lString) {
var storeText = lString;
localStorage.setItem(storeTitle, storeText);
console.info("Locally stored " + storeTitle.toUpperCase() + " with " + storeText.substring(0, 10) + "... As text.");
};
this.removeL = function() {
localStorage.removeItem(storeTitle);
console.info("Locally removed " + storeTitle + ".");
};
this.getL = function () {
localStorage.getItem(storeTitle);
console.info("Locally got string of " + storeTitle + ": " + localStorage.getItem(storeTitle));
};
};
You could use JavaScript closures. In particular look at the "Using Closures for the Module Pattern" section of this webpage for a full description. The idea is to have the function return an literal with all the required methods. Any functions or variables that you want to be kept private are just local variables for the function.

Confusion about object oriented javascript

I'm practicing object oriented syntax in javascript and am having some problems. This is my code:
<html>
<head>
<script type="text/javascript">
function Name(first,mid,last) {
this.first = first;
this.middle = mid;
this.last = last;
}
Name.prototype.fullname = function () {
return this.first + " " + this.middle + " " + this.last;
}
Name.prototype.fullnamereversed = function() {
return this.last + " " + this.middle + " " + this.first;
}
var s = new Name("James","Harlow","Smith")
</script>
</head>
<body>
<script type="text/javascript">
document.body.innerHTML = s.fullname;
document.body.innerHTML = s.fullnamereversed;
</script>
</body>
</html>
When I load the page, the innerHTML of the body is the exact text of Name.protoype ("function ()... this.first + this.middle + this.last..."). What have I done wrong here?
You need to call the functions with the () operator:
document.body.innerHtml = s.fullname();
You are assigning a function to the prototype, therefore you need to call it as such:
<script type="text/javascript">
document.body.innerHTML = s.fullname() + ' ' + s.fullnamereversed();
</script>
You need to invoke your function: document.body.innerHTML = s.fullname();
Example here.
document.body.innerHTML = s.fullname; sets the innerHTML to the function s.fullname.
If you want to set the innerHTML to what the function returns, then you need to actually call the function:
document.body.innerHTML = s.fullname();

Categories