Context page
What is "this"? Learn about context and build your very own . operator!
Overview
- Rules for setting context
 - proto & prototype: A visual representation
 - Exercise!
 
Video
Slides
Exercise: DOT operator
The problem
Write the DOT (.) operator as if it was implemented in JS as a function.
For example, the following uses the DOT operator to read properties from person:
var Person = function(name) {
    this.name = name;
}
Person.prototype.isPerson = true;
var person = new Person('Smith');
DOT(person, 'name');        //person.name
DOT(person, 'isPerson');    //person.isPerson
To solve this problem, DOT should read from the proto chain. While it can be implemented as simple as the following:
const DOT = function(obj, property){
    return obj[property];
}
You should instead only use the [] property accessor when you know the object has
that direct property.
To get started, click the button at the bottom of the following:
<div id="qunit"></div>
<link rel="stylesheet" href="//code.jquery.com/qunit/qunit-1.12.0.css">
<script src="//code.jquery.com/qunit/qunit-1.12.0.js"></script>
<script type="module">
/* start DOT code here */
function DOT(object, property) {
}
/* end DOT code */
// Test code. There’s no need to edit the following:
QUnit.test("DOT works", function(){
    var Person = function(name){
        this.name = name;
    }
    Person.prototype.species = 'Homo Sapien';
    Person.prototype.speak =function(toWhom) {
        return 'Hello ' + toWhom + '. My name is ' + this.name + '.';
    }
    var person = new Person('Alexis');
    var species = DOT(person, 'species');
    var toString = DOT(person, 'toString');
    QUnit.equal(species, 'Homo Sapien', 'property accessed');
    QUnit.equal(toString, Object.prototype.toString,
        'Object.prototype.toString accessed');
    QUnit.equal(DOT(person, 'foobar'), undefined, 'property not found');
});
</script>
What you need to know
- The 
DOTfunction will take an object and a property name as a string. - hasOwnProperty returns if an object has a direct property:
var obj = {foo: "bar"}; console.log( obj.hasOwnProperty("foo") ) // Logs: true 
- Object.getPrototypeOf(obj) returns the 
__proto__value of the passed obj. This is the recommended way of reading the__proto__property.var date = new Date() console.log( Object.getPrototypeOf(date) === Date.prototype ) // Logs: true 
- Recursive functions call themselves to answer a sub-problem:
function factorial(number){ if (number === 0) { return 1; } else { return number * factorial(number-1); } } console.log( factorial(4) ) // Logs: 24 
The solution
<div id="qunit"></div>
<link rel="stylesheet" href="//code.jquery.com/qunit/qunit-1.12.0.css">
<script src="//code.jquery.com/qunit/qunit-1.12.0.js"></script>
<script type="module">
/* start DOT code here */
function DOT(object, property) {
    if( Object.prototype.hasOwnProperty.call(object, property) ) {
        return object[property];
    }
    var proto = Object.getPrototypeOf(object);
    if( proto ) {
        return DOT(proto, property);
    }
}
/* end DOT code */
// Test code. There’s no need to edit the following:
QUnit.test("DOT works", function(){
    var Person = function(name){
        this.name = name;
    }
    Person.prototype.species = 'Homo Sapien';
    Person.prototype.speak =function(toWhom) {
        return 'Hello ' + toWhom + '. My name is ' + this.name + '.';
    }
    var person = new Person('Alexis');
    var species = DOT(person, 'species');
    QUnit.equal(species, 'Homo Sapien', 'property accessed');
    QUnit.equal(DOT(person, 'foobar'), undefined, 'property not found');
});
</script>
Exercise: DOTCALL operator
The problem
Write the dot (.) [[call]] operator as if it was implemented in JS.
For example, instead of calling person.speak("Hi"), we will call it as
DOTCALL(person,"speak",["Hi"]) as follows:
const Person = function(name) {
    this.name = name;
}
Person.prototype.speak = function(message){
  console.log(message + ' ' + this.name);
}
var person = new Person('Smith');
DOTCALL(person,"speak",["Hi"])  //person.speak("Hi")
DOTCALL( obj, prop, args ) will take:
- obj - the context of the function to call.
 - prop - the property name to lookup.
 - args - an array of arguments to pass to the function.
 
To get started, click the Run in your browser button at the bottom of the following code sample:
<div id="qunit"></div>
<link rel="stylesheet" href="//code.jquery.com/qunit/qunit-1.14.0.css">
<script src="//code.jquery.com/qunit/qunit-1.14.0.js"></script>
<script type="module">
// The DOT operator will be useful
function DOT(object, property) {
    if( Object.prototype.hasOwnProperty.call(object, property) ) {
        return object[property];
    }
    var proto = Object.getPrototypeOf(object);
    if( proto ) {
        return DOT(proto, property);
    }
}
function DOTCALL(obj, prop, args){
}
</script>
<script>
QUnit.test('DOTCALL works', function() {
    var Person = function(name){
        this.name = name;
    };
    Person.prototype.species = 'Homo Sapien';
    Person.prototype.speak = function(toWhom) {
        return 'Hello ' + toWhom + '. My name is ' + this.name + '.';
    };
    var person = new Person('Alexis');
    var speak = DOTCALL(person, 'speak', ['Justin']);
    var greet = 'Hello Justin. My name is Alexis.';
    equal(speak, greet, 'method called with argument');
});
</script>
What you need to know
- Use apply to
call a function (also constructor functions) with a 
thisvalue and an array of arguments. - If the call operator (
()) is used on a value that is not a function, an error is thrown. For this example, throw:
wherethrow new Error("${prop} is not a function");propis the name of the property that is being called. 
The solution
<div id="qunit"></div>
<link rel="stylesheet" href="//code.jquery.com/qunit/qunit-1.14.0.css">
<script src="//code.jquery.com/qunit/qunit-1.14.0.js"></script>
<script type="module">
// The DOT operator will be useful
function DOT(object, property) {
    if( Object.prototype.hasOwnProperty.call(object, property) ) {
        return object[property];
    }
    var proto = Object.getPrototypeOf(object);
    if( proto ) {
        return DOT(proto, property);
    }
}
function DOTCALL(obj, prop, args){
    var fn = DOT(obj, prop);
    if(typeof fn === "function") {
        return fn.apply(obj, args);
    } else {
        throw new Error(prop+" is not a function");
    }
}
</script>
<script>
QUnit.test('DOTCALL works', function() {
    var Person = function(name){
        this.name = name;
    };
    Person.prototype.species = 'Homo Sapien';
    Person.prototype.speak = function(toWhom) {
        return 'Hello ' + toWhom + '. My name is ' + this.name + '.';
    };
    var person = new Person('Alexis');
    var speak = DOTCALL(person, 'speak', ['Justin']);
    var greet = 'Hello Justin. My name is Alexis.';
    equal(speak, greet, 'method called with argument');
});
</script>