KEMBAR78
Using JS to teach JS at Khan Academy | PDF
Using JS to teach JS

@ Khan Academy
John Resig (ejohn.org)
http://khanacademy.org/cs
Teaching CS
• At Khan Academy we teach programming
concepts to young students
• …currently 1.3 million of them a month!
• It’s really hard to do this!
• Building a real-time JavaScript editor
• Using static analysis to build challenges
• Writing JavaScript on a tablet or phone
Demo: Live Coding
Editor
https://github.com/Khan/live-editor
Step 1: Error Messages
• All code is run through JSHint
• And through an extra layer of error
handling (called “BabyHint”)
BabyHint
• Handles common mistakes:
• Spelling and case:“strokeWeight” vs.
“strokeweight”
• Gives sane errors about missing semicolons
• Provide hints about correct function arguments
strokeWeight(); (gives an error asking for more
args)
• Check for function declaration mistakes and
possible spacing mistakes (“vartest”)
Step 2:Worker Threads
• Run JavaScript code asynchronously in the
background of a page
• Available in Chrome, Firefox, Safari, and IE
10 (Need to make sure it works in IE 9!)
• Works by doing a string-only postMessage
to the worker and waiting for a response
Step 3: ExtractingValues
• var obj = { name:“John”, city:“Boston” };

with (obj) {

name += “ Resig”;

city = “Brooklyn”;

}
• obj.name === “John Resig”

obj.city === “Brooklyn”
With Statements
• var obj = { name:“John”, city:“Boston” };

with (obj) {

var city = “Brooklyn”;

var job = “Khan Academy”;

}
• obj.city === “Brooklyn”

obj.job === undefined
Example
• var x = 5, y = 1;

var draw = function() {

x += y;

};
• Values: {

x:“5”,

y:“1”,

draw:“function() { x += y; }”

}
Example (cont.)
• var x = 50, y = 1;

var draw = function() {

x += y;

};
• Values: {

x:“50”,

y:“1”,

draw:“function() { x += y; }”

}
• Compare with last value: oldX !== x
• Eval:“var x = 50;”
Demo 2: Challenges
and Parsing
Abstract Syntax Trees!
(ASTs)
• We use ESPrima to parse the user’s code
{
"type": "Program",
"body": [
{
"type": "ExpressionStatement",
"expression": {
"type": "CallExpression",
"callee": {
"type": "Identifier",
"name": "ellipse"
},
"arguments": [
{
"type": "Literal",
"value": 100,
"raw": "100"
},
{
"type": "Literal",
"value": 200,
"raw": "200"
},
{
"type": "Literal",
ellipse(100, 200, 300, 400);
Did a user call a
specific function?
• We can search through the the tree and
look for certain values
• if (obj.type === “CallExpression” &&

obj.callee.name === “ellipse”) { … }
Complexity
• What happens if we want to check for
something more complex?
• checkCode(code, {

method: {

name:“ellipse”,

args: [100, 200, 300, 400]

}

});
…
• But what if we want to check for more
than one function?
• What if the order matters?
• What about other things? if statements?
variables? loops?
• … this model doesn’t hold up well.
Demo 3: Structured JS
Testing
https://github.com/Khan/structuredjs
var oneFill = function() {
fill(_, _, _);
};
var twoFills = function() {
fill(_, _, _);
fill();
};
result = match(structure(oneFill));
if (passes(result)) {
if (!matches(structure(twoFills))) {
result = fail(
$._("Use another fill command for the cup!"));
}
}
var checkSameColor = function() {
var pattern = function() {
fill($a, $b, $c);
fill($a, $b, $c);
fill($a, $b, $c);
}
if (matches(structure(pattern))) {
return fail($._("You're using the same color for
fill three times! Use a different color!
Remember you can click the numbers in the
fill command and then use your mouse to select
a different color."));
}
return pass();
}
Demo 4: Mobile
https://github.com/Khan/structured-blocks
JSRules.addRule(JSASTRule.extend({
image: "ellipse.png",
structure: function() {
ellipse($x_number, $y_number,

$width_number, $height_number);
}
}));
ellipse($x_number, $y_number, $width_number, $height_number);
ellipse(100, 40, 50, 50);
x_number = 100
y_number = 40
width_number = 50
height_number = 50
ellipse($x_number, $y_number, $width_number, $height_number);
ellipse(100, 40, 50, 50);
x_number = 100
y_number = 40
width_number = 50
height_number = 50
Using escodegen
Links
Curriculum:
https://www.khanacademy.org/cs
Code:
https://github.com/Khan/live-editor
https://github.com/Khan/structuredjs
https://github.com/Khan/structured-blocks

Using JS to teach JS at Khan Academy

  • 1.
    Using JS toteach JS
 @ Khan Academy John Resig (ejohn.org) http://khanacademy.org/cs
  • 2.
    Teaching CS • AtKhan Academy we teach programming concepts to young students • …currently 1.3 million of them a month! • It’s really hard to do this!
  • 3.
    • Building areal-time JavaScript editor • Using static analysis to build challenges • Writing JavaScript on a tablet or phone
  • 4.
  • 5.
    Step 1: ErrorMessages • All code is run through JSHint • And through an extra layer of error handling (called “BabyHint”)
  • 6.
    BabyHint • Handles commonmistakes: • Spelling and case:“strokeWeight” vs. “strokeweight” • Gives sane errors about missing semicolons • Provide hints about correct function arguments strokeWeight(); (gives an error asking for more args) • Check for function declaration mistakes and possible spacing mistakes (“vartest”)
  • 7.
    Step 2:Worker Threads •Run JavaScript code asynchronously in the background of a page • Available in Chrome, Firefox, Safari, and IE 10 (Need to make sure it works in IE 9!) • Works by doing a string-only postMessage to the worker and waiting for a response
  • 8.
    Step 3: ExtractingValues •var obj = { name:“John”, city:“Boston” };
 with (obj) {
 name += “ Resig”;
 city = “Brooklyn”;
 } • obj.name === “John Resig”
 obj.city === “Brooklyn”
  • 9.
    With Statements • varobj = { name:“John”, city:“Boston” };
 with (obj) {
 var city = “Brooklyn”;
 var job = “Khan Academy”;
 } • obj.city === “Brooklyn”
 obj.job === undefined
  • 10.
    Example • var x= 5, y = 1;
 var draw = function() {
 x += y;
 }; • Values: {
 x:“5”,
 y:“1”,
 draw:“function() { x += y; }”
 }
  • 11.
    Example (cont.) • varx = 50, y = 1;
 var draw = function() {
 x += y;
 }; • Values: {
 x:“50”,
 y:“1”,
 draw:“function() { x += y; }”
 } • Compare with last value: oldX !== x • Eval:“var x = 50;”
  • 12.
  • 13.
    Abstract Syntax Trees! (ASTs) •We use ESPrima to parse the user’s code
  • 14.
    { "type": "Program", "body": [ { "type":"ExpressionStatement", "expression": { "type": "CallExpression", "callee": { "type": "Identifier", "name": "ellipse" }, "arguments": [ { "type": "Literal", "value": 100, "raw": "100" }, { "type": "Literal", "value": 200, "raw": "200" }, { "type": "Literal", ellipse(100, 200, 300, 400);
  • 15.
    Did a usercall a specific function? • We can search through the the tree and look for certain values • if (obj.type === “CallExpression” &&
 obj.callee.name === “ellipse”) { … }
  • 16.
    Complexity • What happensif we want to check for something more complex? • checkCode(code, {
 method: {
 name:“ellipse”,
 args: [100, 200, 300, 400]
 }
 });
  • 17.
    … • But whatif we want to check for more than one function? • What if the order matters? • What about other things? if statements? variables? loops? • … this model doesn’t hold up well.
  • 18.
    Demo 3: StructuredJS Testing https://github.com/Khan/structuredjs
  • 19.
    var oneFill =function() { fill(_, _, _); }; var twoFills = function() { fill(_, _, _); fill(); }; result = match(structure(oneFill)); if (passes(result)) { if (!matches(structure(twoFills))) { result = fail( $._("Use another fill command for the cup!")); } }
  • 20.
    var checkSameColor =function() { var pattern = function() { fill($a, $b, $c); fill($a, $b, $c); fill($a, $b, $c); } if (matches(structure(pattern))) { return fail($._("You're using the same color for fill three times! Use a different color! Remember you can click the numbers in the fill command and then use your mouse to select a different color.")); } return pass(); }
  • 21.
  • 22.
    JSRules.addRule(JSASTRule.extend({ image: "ellipse.png", structure: function(){ ellipse($x_number, $y_number,
 $width_number, $height_number); } }));
  • 23.
    ellipse($x_number, $y_number, $width_number,$height_number); ellipse(100, 40, 50, 50); x_number = 100 y_number = 40 width_number = 50 height_number = 50
  • 24.
    ellipse($x_number, $y_number, $width_number,$height_number); ellipse(100, 40, 50, 50); x_number = 100 y_number = 40 width_number = 50 height_number = 50 Using escodegen
  • 25.