Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

I am getting the following errors: g++ -c -g -MMD -MP -MF \"build/Debug/Cygwin_4

ID: 3561294 • Letter: I

Question

I am getting the following errors:

g++    -c -g -MMD -MP -MF "build/Debug/Cygwin_4.x-Windows/main.o.d" -o build/Debug/Cygwin_4.x-Windows/main.o main.cpp
In file included from bag6.h:73:0,
                 from main.cpp:4:
bag6.template:13:22: error: variable or field 'bst_remove_max' declared void
void bst_remove_max(binary_tree_node<Item>*& root_ptr, Item& removed);
                      ^
bag6.template:13:22: error: 'binary_tree_node' was not declared in this scope
bag6.template:13:43: error: expected primary-expression before '>' token
void bst_remove_max(binary_tree_node<Item>*& root_ptr, Item& removed);
                                           ^
bag6.template:13:47: error: 'root_ptr' was not declared in this scope
void bst_remove_max(binary_tree_node<Item>*& root_ptr, Item& removed);
                                               ^
bag6.template:13:61: error: expected primary-expression before '&' token
void bst_remove_max(binary_tree_node<Item>*& root_ptr, Item& removed);
                                                             ^
bag6.template:13:63: error: 'removed' was not declared in this scope
void bst_remove_max(binary_tree_node<Item>*& root_ptr, Item& removed);
                                                               ^
bag6.template:20:2: error: expected unqualified-id before '{' token
{
^
main.cpp:132:2: error: expected '}' at end of input
};
^

______________________________________________________________________________

Here is the code:

______________________________________________________________________________

// main.cpp

#include <ctype.h>    // Provides toupper
#include <iostream> // Provides cout, cin
#include <stdlib.h>   // Provides EXIT_SUCCESS, size_t
#include "bag6.h"     // Provides the Bag template class

using std::cout;
using std::endl;
using std::cin;

  

// PROTOTYPES for the functions used in this test program.
void print_menu( );
// Postcondition: A menu of choices for this program has been written to cout.

char get_user_command( );
// Postcondition: The user has been prompted to enter a one character command.
// A line of input (with at least one character) has been read, and the first
// character of the input line is returned.

void show_bags(const Bag<int>& b1, const Bag<int>& b2);
// Postcondition: The function has tested whether the numbers 0..9 are in
// the two bags, and printed the results to standard output.

Bag<int> copybag(Bag<int> b);
// Postcondition: The return value is a copy of b.

int get_number( );
// Postcondition: The user has been prompted to enter an int number. The
// number has been read, echoed to the screen, and returned by the function.

int main( )
{
    Bag<int> b1, b2;   // Bags that we'll perform tests on
    char choice; // A command character entered by the user

    cout << "I have initialized two empty bags of ints." << endl;

    do
    {
        print_menu( );
        choice = get_user_command( );
        switch (choice)
        {
            case 'C': b1 = copybag(b2);
                      break;
            case 'c': b2 = copybag(b1);
                      break;
            case 'S':
            case 's': cout << "The bag's sizes are " << b1.size( );
                      cout << " and " << b2.size( ) << endl;
                      break;
            case 'I': b1.insert(get_number( ));
                      break;
            case 'i': b2.insert(get_number( ));
                      break;
            case 'R': b1.remove(get_number( ));
                      break;
            case 'r': b2.remove(get_number( ));
                      break;
            case 'O':
            case 'o': show_bags(b1, b2);
                      break;
            case '+': b1 += b2;
                      break;
        case 'q':
        case 'Q': cout << "Ridicule is the best test of truth." << endl;
                      break;
            default: cout << choice << " is invalid. Sorry." << endl;
        }
    }
    while ((toupper(choice) != 'Q'));

    return EXIT_SUCCESS;

}

void print_menu( )
// Library facilties used: iostream.h
{
    cout << "The following choices are available with 2 bags: " << endl;
    cout << " C Use the copy constructor to make b1 equal to b2" << endl;
    cout << " c Use the copy constructor to make b2 equal to b1" << endl;
    cout << " I Insert an item into b1" << endl;
    cout << " i Insert an item into b2" << endl;
    cout << " R Remove an item from b1" << endl;
    cout << " r Remove an item from b2" << endl;
    cout << " O Test for occurrence of items 0-9 in b1 and b2" << endl;
    cout << " + Execute b1 += b2;" << endl;
    cout << " S Print the result from the size( ) functions" << endl;
    cout << " Q Quit this test program" << endl;
}

char get_user_command( )
// Library facilties used: iostream.h
{
    char command;

    cout << "Enter choice: ";
    cin >> command;

    return command;
}

void show_bags(const Bag<int>& b1, const Bag<int>& b2)
// Library facilties used: iostream.h
{
    int i;

    for (i = 0; i < 10; i++)
    {
        cout << i << "in b1? " << b1.occurrences(i);
        cout << " in b2? " << b2.occurrences(i) << endl;
    }
}

Bag<int> copybag(Bag<int> b)
{
    return b;
}

int get_number( )
// Library facilties used: iostream.h
{
    int result;

    cout << "Please enter an integer number for the bag: ";
    cin >> result;
    cout << result << " has been read." << endl;
    return result;
}
};

//bag6.h

// FILE: bag6.h
// TEMPLATE CLASS PROVIDED: Bag<Item> (a container class for a collection of
// items). The template parameter, Item, is the data type of the items in the
// bag. It may be any of the C++ built-in types (int, char, etc.), or a class
// with a default constructor, a copy constructor, an assignment operator, and
// the six comparison operators forming a total order.
//
// CONSTRUCTOR for the Bag<Item> template class:
//   Bag( )
//     Postcondition: The bag is empty.
//
// MODIFICATION MEMBER FUNCTIONS for the Bag<Item> template class:
//   void insert(const Item& entry)
//     Postcondition: A new copy of entry has been inserted into the bag.
//
//   void remove(const Item& target)
//     Postcondition:If target was in the bag, then one copy of target has
//     been removed from the bag; otherwise the bag is unchanged.
//
//   void operator +=(const Bag& addend)
//     Postcondition: Each item in addend has been added to this bag.
//
// CONSTANT MEMBER FUNCTIONS for the Bag<Item> template class:
//   size_t size( ) const
//     Postcondition: Return value is the total number of items in the bag.
//
//   size_t occurrences(const Item& target) const
//     Postcondition: Return value is number of times target is in the bag.
//
// NONMEMBER functions for the Bag<Item> template class:
//   Bag operator +(const Bag& b1, const Bag& b2)
//     Postcondition: The bag returned is the union of b1 and b2.
//
// VALUE SEMANTICS for the Bag<Item> template class:
//   Assignments and the copy constructor may be used with Bag objects.
//
// DYNAMIC MEMORY USAGE by the Bag<Item> template class:
//   If there is insufficient dynamic memory,
//   then the following functions call new_handler: The constructors,
//   insert, operator +=, operator +, and the assignment operator.

#ifndef BAG_H
#define BAG_H
#include <stdlib.h>   // Provides size_t and NULL
#include "bintree2.h" // Provides BinaryTreeNode and related functions


    template <class Item>
    class Bag
    {
    public:
        // CONSTRUCTORS and DESTRUCTOR
        Bag( ) { root_ptr = NULL; }
        Bag(const Bag<Item>& source);
        ~Bag( );
        // MODIFICATION functions
        void insert(const Item& entry);
        void remove(const Item& target);
        void operator +=(const Bag<Item>& addend);
        void operator =(const Bag<Item>& source);
        // CONSTANT functions
        size_t size( ) const;
        size_t occurrences(const Item& target) const;
    private:
        BinaryTreeNode<Item> *root_ptr; // Root pointer of binary search tree
        void insert_all(BinaryTreeNode<Item>* addroot_ptr);
    };

    // NONMEMBER functions for the Bag
    template <class Item>
    Bag<Item> operator +(const Bag<Item>& b1, const Bag<Item>& b2);

#include "bag6.template"
#endif

//bintree2.template

// FILE: bt_tool2.template
// IMPLEMENTS: The nine template functions of the second version of the binary
// tree toolkit (see bintree2.h for documentation). Note that this file is not
// compiled on its own. Instead, this file is included by an include directive
// at the bottom of bintree2.h.

#include <assert.h>    // Provides assert
#include <iomanip>   // Provides setw
#include <iostream> // Provides cout
#include <stdlib.h>    // Provides NULL, size_t

using std::cout;
using std::endl;
using std::cin;

  

// Programming note: Some compilers require that the default argument is
// listed in the implementation as well as the prototype, so we have
// include the default arguments for create_node.
template <class Item>
BinaryTreeNode<Item>* create_node(
    const Item& entry,
    BinaryTreeNode<Item>* l_ptr = NULL,
    BinaryTreeNode<Item>* r_ptr = NULL
)
{
    BinaryTreeNode<Item>* result_ptr;

    result_ptr = new BinaryTreeNode<Item>;
    result_ptr->data = entry;
    result_ptr->left = l_ptr;
    result_ptr->right = r_ptr;

    return result_ptr;
}

template <class Item>
BinaryTreeNode<Item>* tree_copy(const BinaryTreeNode<Item>* root_ptr)
// Library facilities used: stdlib.h
{
    BinaryTreeNode<Item> *l_ptr;
    BinaryTreeNode<Item> *r_ptr;

    if (root_ptr == NULL)
        return NULL;
    else
    {
        l_ptr = tree_copy(root_ptr->left);
        r_ptr = tree_copy(root_ptr->right);
        return create_node(root_ptr->data, l_ptr, r_ptr);
    }
}

template <class Item>
void tree_clear(BinaryTreeNode<Item>*& root_ptr)
{
    if (root_ptr != NULL)
    {
        tree_clear(root_ptr->left);
        tree_clear(root_ptr->right);
        delete root_ptr;
        root_ptr = NULL;
    }
}

template <class Item>
bool is_leaf(const BinaryTreeNode<Item>& node)
{
    return (node.left == NULL) && (node.right == NULL);
}

template <class Item, class Processor>
void inorder(BinaryTreeNode<Item>* node_ptr, Processor f)
{
    if (node_ptr != NULL)
    {
        inorder(node_ptr->left, f);
        f(node_ptr->data);
        inorder(node_ptr->right, f);
    }
}

template <class Item, class Processor>
void postorder(BinaryTreeNode<Item>* node_ptr, Processor f)
{
    if (node_ptr != NULL)
    {
        postorder(node_ptr->left, f);
        postorder(node_ptr->right, f);
        f(node_ptr->data);
    }
}

template <class Item, class Processor>
void preorder(BinaryTreeNode<Item>* node_ptr, Processor f)
{
    if (node_ptr != NULL)
    {
        f(node_ptr->data);
        preorder(node_ptr->left, f);
        preorder(node_ptr->right, f);
    }
}

template <class Item, class SizeType>
void print(BinaryTreeNode<Item>* node_ptr, SizeType depth)
// Library facilities used: iomanip.h, iostream.h, stdlib.h
{
    if (node_ptr != NULL)
    {
        print(node_ptr->right, depth+1);
        cout << setw(4*depth) << ""; // Indent 4*depth spaces
        cout << node_ptr->data << endl;
        print(node_ptr->left, depth+1);
    }
}

template <class Item>
size_t tree_size(const BinaryTreeNode<Item>* node_ptr)
// Library facilities used: stdlib.h
{
    if (node_ptr == NULL)
        return 0;
    else
        return 1 + tree_size(node_ptr->left) + tree_size(node_ptr->right);
}

// bag6.template

// FILE: bag6.template
// TEMPLATE CLASS IMPLEMENTED: bag<Item> (see bag6.h for documentation)
// INVARIANT of the ADT:
//   root_ptr is the root pointer of a binary search tree that contains the
//   bag's items.

#include <cassert>
#include <cstdlib>

namespace main_savitch_10
{
    template <class Item>
   void bst_remove_max(binary_tree_node<Item>*& root_ptr, Item& removed);
   // Precondition: root_ptr is a root pointer of a non-empty binary
   // search tree.
   // Postcondition: The largest item in the binary search tree has been
   // removed, and root_ptr now points to the root of the new (smaller)
   // binary search tree. The reference parameter, removed, has been set
   // to a copy of the removed item.
   {
        binary_tree_node<Item> *oldroot_ptr;

        assert(root_ptr != NULL);

        if (root_ptr->right( ) != NULL)
       bst_remove_max(root_ptr->right( ), removed);
        else
        {
       removed = root_ptr->data( );
       oldroot_ptr = root_ptr;
       root_ptr = root_ptr->left( );
       delete oldroot_ptr;
        }
   }

    template <class Item>
   bool bst_remove(binary_tree_node<Item>*& root_ptr, const Item& target)
   // Precondition: root_ptr is a root pointer of a binary search tree
   // or may be NULL for an empty tree).
   // Postcondition: If target was in the tree, then one copy of target
   // has been removed, and root_ptr now points to the root of the new
   // (smaller) binary search tree. In this case the function returns true.
   // If target was not in the tree, then the tree is unchanged (and the
   // function returns false).
   {
        binary_tree_node<Item> *oldroot_ptr;
      
        if (root_ptr == NULL)
        {   // Empty tree
       return false;
        }

        if (target < root_ptr->data( ))
        {   // Continue looking in the left subtree
       return bst_remove(root_ptr->left( ), target);
        }

        if (target > root_ptr->data( ))
        {   // Continue looking in the right subtree
       return bst_remove(root_ptr->right( ), target);
        }
      
        if (root_ptr->left( ) == NULL)
        {   // Target was found and there is no left subtree, so we can
       // remove this node, making the right child be the new root.
       oldroot_ptr = root_ptr;
       root_ptr = root_ptr->right( );
       delete oldroot_ptr;
       return true;
        }
      
        // If code reaches this point, then we must remove the target from
        // the current node. We'll actually replace this target with the
        // maximum item in our left subtree.
        bst_remove_max(root_ptr->left( ), root_ptr->data( ));
        return true;
   }

    template <class Item>
   typename bag<Item>::size_type bst_remove_all
   (binary_tree_node<Item>*& root_ptr, const Item& target)
   // Precondition: root_ptr is a root pointer of a binary search tree
   // or may be NULL for an empty tree).
   // Postcondition: All copies of target have been removed from the tree
   // has been removed, and root_ptr now points to the root of the new
   // (smaller) binary search tree. The return value tells how many copies
   // of the target were removed.
   {
        binary_tree_node<Item> *oldroot_ptr;
      
        if (root_ptr == NULL)
        {   // Empty tree
       return 0;
        }

        if (target < root_ptr->data( ))
        {   // Continue looking in the left subtree
       return bst_remove_all(root_ptr->left( ), target);
        }

        if (target > root_ptr->data( ))
        {   // Continue looking in the right subtree
       return bst_remove_all(root_ptr->right( ), target);
        }
      
        if (root_ptr->left( ) == NULL)
        {   // Target was found and there is no left subtree, so we can
       // remove this node, making the right child be the new root.
       oldroot_ptr = root_ptr;
       root_ptr = root_ptr->right( );
       delete oldroot_ptr;
       return 1;
        }
      
        // If code reaches this point, then we must remove the target from
        // the current node. We'll actually replace this target with the
        // maximum item in our left subtree. We then continue
        // searching for more copies of the target to remove.
        // This continued search must start at the current root (since
        // the maximum element that we moved up from our left subtree
        // might also be a copy of the target).
        bst_remove_max(root_ptr->left( ), root_ptr->data( ));
        return 1 + bst_remove_all(root_ptr, target);
   }

    template <class Item>
   bag<Item>::bag(const bag<Item>& source)
   // Library facilities used: bintree.h
   {
        root_ptr = tree_copy(source.root_ptr);
   }

    template <class Item>
   bag<Item>::~bag( )
   // Header file used: bintree.h
   {
        tree_clear(root_ptr);
   }

    template <class Item>
   typename bag<Item>::size_type bag<Item>::size( ) const
   // Header file used: bintree.h
   {
        return tree_size(root_ptr);
   }

    template <class Item>
   void bag<Item>::insert(const Item& entry)
   // Header file used: bintree.h
   {
        binary_tree_node<Item> *cursor = root_ptr;
        bool done = false;
  
        if (root_ptr == NULL)
        {
       root_ptr = new binary_tree_node<Item>(entry);
       return;
        }
  
        do
        {
       if (cursor->data( ) >= entry)
       {   // Go left
            if (cursor->left( ) == NULL)
            {
           cursor->set_left( new binary_tree_node<Item>(entry) );
           done = true;
            }
            else
           cursor = cursor->left( );
       }
       else
       {   // Go right
            if (cursor->right( ) == NULL)
            {
           cursor->set_right( new binary_tree_node<Item>(entry) );
           done = true;
            }
            else
           cursor = cursor->right( );
       }
        }   while (!done);
   }

    template <class Item>
   typename bag<Item>::size_type bag<Item>::count(const Item& target) const
   {
        size_type answer = 0;
        binary_tree_node<Item> *cursor = root_ptr;

        while (cursor != NULL)
        {
       if (cursor->data( ) < target)
            cursor = cursor->right( );
       else
       {
            if (cursor->data( ) == target) answer++;
            cursor = cursor->left( );
       }
        }
        return answer;
   }

    template <class Item>
   typename bag<Item>::size_type bag<Item>::erase(const Item& target)
   {
        return bst_remove_all(root_ptr, target);
   }

    template <class Item>
   bool bag<Item>::erase_one(const Item& target)
   {
        return bst_remove(root_ptr, target);
   }

    template <class Item>
   void bag<Item>::operator =(const bag<Item>& source)
        // Header file used: bintree.h
        {
        if (root_ptr == source.root_ptr)
            return;
        tree_clear(root_ptr);
        root_ptr = tree_copy(source.root_ptr);
   }

    template <class Item>
   void bag<Item>::operator +=(const bag<Item>& addend)
        {
        if (root_ptr == addend.root_ptr)
        {
       bag<Item> copy = addend;
       insert_all(copy.root_ptr);
        }
        else
            insert_all(addend.root_ptr);
   }

    template <class Item>
   bag<Item> operator +(const bag<Item>& b1, const bag<Item>& b2)
   {
        bag<Item> answer = b1;
        answer += b2;
        return answer;
   }

    template <class Item>
   void bag<Item>::insert_all(binary_tree_node<Item>* addroot_ptr)
        // Precondition: addroot_ptr is the root pointer of a binary search tree that
        // is separate for the binary search tree of the bag that activated this
        // method.
        // Postcondition: All the items from the addroot_ptr's binary search tree
        // have been added to the binary search tree of the bag that activated this
        // method.
   {
        if (addroot_ptr != NULL)
        {
       insert(addroot_ptr->data( ));
       insert_all(addroot_ptr->left( ));
       insert_all(addroot_ptr->right( ));
        }
   }
}

//bintree2.h

// FILE: bintree.h
// PROVIDES: An expanded toolkit of nine template functions for manipulating
// binary trees. Each node of the tree contains a piece of data and pointers
// to its left and right children as shown here:
//
//     template <class Item>       Item may be any of the C++ built-in types
//     struct BinaryTreeNode       (int, char, etc.), or a class with a default
//     {                           constructor, and an assignment operator.
//         Item data;
//         BinaryTreeNode *left;  
//         BinaryTreeNode *right;
//     }
//
// The left and right pointers may be NULL to indicate no child. Each tree
// is accessed through a pointer to its root. A NULL root pointer indicates an
// empty tree.
//
// FUNCTIONS in the binary tree toolkit:
//   template <class Item>
//   BinaryTreeNode<Item>* create_node(
//       const Item& entry,
//       BinaryTreeNode<Item>* l_ptr = NULL,
//       BinaryTreeNode<Item>* r_ptr = NULL
//   )
//     Postcondition: The value returned is a pointer to a newly allocated node
//     with its data equal to entry, and its child pointers equal to l_ptr and
//     r_ptr. Note: If there is insufficient dynamic memory, then the
//     new_handler is called.
//
//   template <class Item>
//   bool is_leaf(const BinaryTreeNode<Item>& node)
//     Postcondition: The return value is true if node is a leaf;
//     otherwise the return value is false.
//
//   template <class Item>
//   void tree_clear(BinaryTreeNode<Item>*& root_ptr)
//     Precondition: root_ptr is the root pointer of a binary tree (which may
//     be NULL for the empty tree).
//     Postcondition: All nodes at the root or below have been returned to the
//     heap, and root_ptr has been set to NULL.
//
//   template <class Item>
//   BinaryTreeNode<Item>* tree_copy(BinaryTreeNode<Item>* root_ptr)
//     Precondition: root_ptr is the root pointer of a binary tree (which may
//     be NULL for the empty tree).
//     Postcondition: A copy of the binary tree has been made, and the return
//     value is a pointer to the root of this copy.
//
//   template <class Item, class Processor>
//   void preorder(BinaryTreeNode<Item>*, Processor f)
//     Precondition: node_ptr is a pointer to a node in a binary
//     tree (or node_ptr may be NULL to indicate the empty tree).
//     Postcondition: If node_ptr is non-NULL, then the function f
//     has been applied to the contents of *node_ptr and all of
//     its descendants, using a pre-order traversal.
//     Note: Process is the type of a function f which may be
//     called with a single Item argument. Item may be any type.
//
//   template <class Item, class Processor>
//   void postorder(BinaryTreeNode<Item>*, Processor f)
//     Same as the preorder function, except with a post-order traversal.
//
//   template <class Item, class Processor>
//   void inorder(BinaryTreeNode<Item>*, Processor f)
//     Same as the preorder function, except with an in-order traversal.
//
//   template <class Item, class SizeType>
//   void print(BinaryTreeNode<Item>* node_ptr, SizeType depth)
//     Precondition: node_ptr is a pointer to a node in a binary
//     tree (or node_ptr may be NULL to indicate the empty tree).
//     If the pointer is not NULL, then depth is the depth of
//     the node pointed to by node_ptr.
//     Postcondition: If node_ptr is non-NULL, then the contents
//     of *node_ptr and all its descendants have been written
//     to cout with the << operator, using a backward in-order
//     traversal. Each node is indented 4 times its depth.
//
//   template <class Item>
//   size_t tree_size(const BinaryTreeNode<Item>* root_ptr)
//     Precondition: node_ptr is a pointer to a node in a binary
//     tree (or node_ptr may be NULL to indicate the empty tree).
//     Postcondition: The return value is the number of nodes in
//     the tree.

#ifndef BT_TOOL2_H
#define BT_TOOL2_H
#include <stdlib.h> // Provides NULL

    template <class Item>
    struct BinaryTreeNode
    {
        Item data;
        BinaryTreeNode* left;
        BinaryTreeNode* right;
    };

    template <class Item>
    BinaryTreeNode<Item>* create_node(
        const Item& entry,
        BinaryTreeNode<Item>* l_ptr = NULL,
        BinaryTreeNode<Item>* r_ptr = NULL
    );

    template <class Item>
    BinaryTreeNode<Item>* tree_copy(const BinaryTreeNode<Item>* root_ptr);

    template <class Item>
    void tree_clear(BinaryTreeNode<Item>*& root_ptr);

    template <class Item>
    bool is_leaf(const BinaryTreeNode<Item>& ptr);

    template <class Item, class Processor>
    void preorder(BinaryTreeNode<Item>*, Processor f);

    template <class Item, class Processor>
    void inorder(BinaryTreeNode<Item>*, Processor f);

    template <class Item, class Processor>
    void postorder(BinaryTreeNode<Item>*, Processor f);

    template <class Item, class SizeType>
    void print(BinaryTreeNode<Item>* node_ptr, SizeType depth);

    template <class Item>
    size_t tree_size(const BinaryTreeNode<Item>* root_ptr);

#include "bintree2.template"
#endif

Explanation / Answer

Object Usage and Properties

Everything in JavaScript acts like an object, with the only two exceptions being null and undefined.

A common misconception is that number literals cannot be used as objects. That is because a flaw in JavaScript's parser tries to parse the dot notation on a number as a floating point literal.

There are a couple of workarounds that can be used to make number literals act as objects too.

Objects as a Data Type

Objects in JavaScript can also be used as Hashmaps; they mainly consist of named properties mapping to values.

Using an object literal - {} notation - it is possible to create a plain object. This new object inherits from Object.prototype and does not have own properties defined.

Accessing Properties

The properties of an object can be accessed in two ways, via either the dot notation or the square bracket notation.

The notations work almost identically, with the only difference being that the square bracket notation allows for dynamic setting of properties and the use of property names that would otherwise lead to a syntax error.

Deleting Properties

The only way to remove a property from an object is to use the delete operator; setting the property to undefined or null only removes the value associated with the property, but not the key.

The above outputs both bar undefined and foo null - only baz was removed and is therefore missing from the output.

Notation of Keys

Object properties can be both notated as plain characters and as strings. Due to another mis-design in JavaScript's parser, the above will throw a SyntaxError prior to ECMAScript 5.

This error arises from the fact that delete is a keyword; therefore, it must be notated as a string literal to ensure that it will be correctly interpreted by older JavaScript engines.

The Prototype

JavaScript does not feature a classical inheritance model; instead, it uses a prototypal one.

While this is often considered to be one of JavaScript's weaknesses, the prototypal inheritance model is in fact more powerful than the classic model. It is, for example, fairly trivial to build a classic model on top of a prototypal model, while the other way around is a far more difficult task.

JavaScript is the only widely used language that features prototypal inheritance, so it can take time to adjust to the differences between the two models.

hasOwnProperty

To check whether an object has a property defined on itself and not somewhere on its prototype chain, it is necessary to use the hasOwnProperty method which all objects inherit from Object.prototype.

Note: It is not enough to check whether a property is undefined. The property might very well exist, but its value just happens to be set to undefined.

hasOwnProperty is the only thing in JavaScript which deals with properties and does not traverse the prototype chain.

Only hasOwnProperty will give the correct and expected result; this is essential when iterating over the properties of any object. There is no other way to exclude properties that are not defined on the object itself, but somewhere on its prototype chain.

hasOwnProperty as a Property

JavaScript does not protect the property name hasOwnProperty; thus, if the possibility exists that an object might have a property with this name, it is necessary to use an external hasOwnProperty to get correct results.

In Conclusion

Using hasOwnProperty is the only reliable method to check for the existence of a property on an object. It is recommended that hasOwnProperty is used in every for in loop to avoid errors from extended native prototypes.

The for in Loop

Just like the in operator, the for in loop traverses the prototype chain when iterating over the properties of an object.

Note: The for in loop will not iterate over any properties that have their enumerable attribute set to false; for example, the length property of an array.

Since it is not possible to change the behavior of the for in loop itself, it is necessary to filter out the unwanted properties inside the loop body; this is done using the hasOwnProperty method of Object.prototype.

Note: Since for in always traverses the complete prototype chain, it will get slower with each additional layer of inheritance added to an object.

Using hasOwnProperty for Filtering

This version is the only correct one to use. Due to the use of hasOwnProperty, it will only print out moo. When hasOwnProperty is left out, the code is prone to errors in cases where the native prototypes - e.g. Object.prototype - have been extended.