408 lines
81 KiB
HTML
408 lines
81 KiB
HTML
|
<!DOCTYPE html>
|
|||
|
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:og="http://ogp.me/ns#" xmlns:fb="http://www.facebook.com/2008/fbml">
|
|||
|
|
|||
|
<head>
|
|||
|
<meta charset="UTF-8">
|
|||
|
<title>calliope mini - Blocks / Javascript editor - calliope</title>
|
|||
|
<meta name="Description" content="A Blocks / JavaScript code editor for the calliope mini." />
|
|||
|
|
|||
|
|
|||
|
<!-- include meta.html -->
|
|||
|
<!-- This file is typically overriden by the target, with own Twitter
|
|||
|
account etc. Most data is taken from the theme file though.
|
|||
|
-->
|
|||
|
|
|||
|
<meta name="twitter:card" content="summary" />
|
|||
|
<meta name="twitter:site" content="@mspxtio" />
|
|||
|
<meta name="twitter:title" content="calliope mini - Blocks / Javascript editor - calliope" />
|
|||
|
<meta name="twitter:description" content="A Blocks / JavaScript code editor for the calliope mini." />
|
|||
|
<meta name="twitter:image" content="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALQAAAC0CAIAAACyr5FlAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QA/wD/AP+gvaeTAAAAB3RJTUUH4AoUFBUNHXD4TgAAG/NJREFUeNrtnXmQHNd933+vp7tnpueenZm9L2CxC3BDHCQIgDYjQbwAXqYsyopcpK0KJVmpVJJyVSqVlFNJlROXS2W5YiuxXFE5ksySypJFy6YpWpZ4SDxFAiQgAAQBEscusJg9Z+fonruP98sfs1gugJ3dnpm+dnc+tUUsge6Z1+99+/d77/d+7z2CiNCmzWowdhegjXNpi6NNXdriaFOXtjja1KUtjjZ1aYujTV3a4mhTl7Y42tSlLY42dWmLo01d2uJoU5e2ONrUhbW7AE5leT6SELuLYhttcQDVtHJBlDJzYmpWyswXcovVUkGRK4BIXC7e7fX4gsFoZyjeHero9kfibo+wRRSzdcWhytX07NVrF04lL5xKJS/nsym5UqSatvrVhLAs5/GHwvGe7uHbBnbu6x4eD0TihNnMfplswXyOQjZ1+czbH534xezlD4r5LDReAy6WCyd6h8cPjN11X8/2cY732P1MprC1xCGl5z9895X33/ynVPJSXSPRCG7BP7jzzj2HHx8aP9C0RFRNu5ac+ejCxMzsvKyoxj4yQ4jPJ2wb6h/bsS0aDTd071YRh1wpnT/28rs/+35q+jJSauyH8x5hZO89Bx96qmt4JyGNOZqZuYXnfvzi28dOZHOSeW3BsuxAf88jRz51+BOHPG63zru2gDgQZybO/fL5b0+8/7aqyOZ9TyCSuOO+J/bd+4QQCOu85dLlK9/4q+9euDhpTU1wHPvwg5966rc/LXi9eq7f5OJQFfmDX/70zef+n7g4Y8HXEYbZvvvXPvnZf9s5OLruxelM9k/+7Jtnz12wskJYl+vJz3/6t37zYaJjwLWZO9vlgvTqD//ixe9+zRplAABSeunUm//wF//lo/d+jriO83r5F299cP6ixXWiatpPfvaLjy5O6Ll404qjkFt86Xt/+u6LP1CqZYu/OjM39dPvfPX0a8+v0ecVpfxb75ywxWynFjOvv3lcz5WbM86Rzy787Jk/uXDytSaGqYZQlDKvfP/P5Upp/wOfY1yrVPLM7Pzs7IJd9XP67Hk9l21Cy1EuiD///tcvnHjVLmXUqJYKb/z9N8+8/uNV/UsuJ8myib3jtUlncnou22ziUKrl13/0zXPvvGR3QQAAquXiq8/+5Yfv/vzWf1I1DcE27eqM8Wwut4J46rV/PPXqc+t2Bi2jlM+++sNvROK9XcO7Vv79rUMFwjDmTdgg4g39G31zQ5tKHFfPn3j7hWc01TZzvSrZ+WuvPvuXj/2bP/QFo/WuIYT0Dg/6QyEwwZwgxenJK/mcqGf4upLNI46ilHnzub8qZFN2F2QVJs8ee+/Fv/3EE19ZI37qCwbCsagZ4xekdH56uokbN0+f4/03Xpj66Fd2l2J1EOmpV59LXjyz5jUm0pw92iTiSCUvn/z5jwyfNDGQopg+9pPvyZWS3QVpgE0hDsQzb7yQW2jGclrJxPtvXz79lt2laIDNII7F2SsfHn/F7lKsjypXT732j9Vy0e6C6GUziOP8sZcsmz1pkeSF09ec2jG6lQ0/WimKmYsnX2/0rj3jO3t7EkhbHhoQoijK8ZPvi1Jez0BRqZY/PP7KyN57bKqtxtjw4piZOLs401g+BCFkaKB3fHwUWhcHQLlSOXv+oijldV5/9fwJcSEJGyH5dMOL48oH76pyteHbEIEitD66IdCowqTMXPLiaeLqtq6OmmUD6HcNKkVp+tL7dpeiMZDSqQ9Paqpid0HWZ2OLQ1yczS0k7S5Fw8xd/ahcEAk4ffHLxhbH4syVclGyuxQNIy3OiYszzu92OL18a5OZverkqGg9quVidj7ZthwmgkhzGyS8cRNUU3OpaRvzOXSygcWhqWpRzNhdimZApIVsCqkBq6pMZSOLQ5GrJb3RBachV4rOd4gbWByUaqrSeITDGaBadf6KoY0tDue/fHVBStp9DlNx/su3odnY4mhjKm1xtKlLWxxt6tIWR5u6bFFxtPuxetiK4kBEVTNqdyVCKVVVp8c6m2OLiqNQKBm1zLpcqZSrGzUWtzZbVBzzqbRmxIZxQMjCYqZcrjS60nBDsBXFQQiZnV/I5qTW95qlqnZ58lrbrWweCCFSvnjuwuVWPQshM/MLE1evbUarAbA1xQEAiHj67IfTcwvQ9L4HhFSq1WPvnS4US5vSp8CWFQchRMoXfvHGsVy2KedCiKqq77x76sLE1c2qDNiy4gAAQsjV5MxPXnl9IZUGQhqQCEPK5crrb7937OT7m3vmb8OvW2kFQsjk1eQ//NNLB/bdvnN0m9ez/v7UqqYlp+aOnTwzcTW5uZUBW9lyLD//nFj8ZRbzVU1P/1RR1EtzuUtXNr8yYIuLgyAtByJThz+344nfi/UM6bnF4wvsvvczsZ6BDZxnpJstKw4EwGzv6JkjTwcPPnBHR4fq7dBzl8b5gr0jtx26d3OftFJj8z/hrRBEyvLJ2z959sjT5b6xIxFf0MVQIUYZbp07ETShg7j4sf2fiHa3ZDzq9H4R0OifpVlGBIQVP7p84pbrkBKkhXDXlbuOLozuV1zcXi+33+9FRPQENXeQqaSh/lojyrDUlyCA4Y5E4uiT/3z8BBKAZtYmoUz5HA0gXr+XAPR2BqNhM+aLEVHy7lUq1eWSIrveawAAW0sciEiYhaHdl+/+jWJiAJC6CRyJ+IMsQxGIi1d9ca6crt/WqPEB9IQIIhCyZ8+BStl3SSoyTcU5CMBNiQN5jo1GQ7ybN+PRSW9i5Vi9qk+DW0UcBKnCC1O7P3lt3/2KECBIKcIun/uugHfJxBJAX4xmOAbrzOYjaEKUsDwAUMQ+gf+Nvtj/PlcwanZXk5X8YjbS2eFyuUypgsbLuSX6HARpIdJ17t4nJw89pgp+ghQAeIbUzMZSnSGCO6jx/nqZQJRxUSG+HA8lAA/1xocDAjVuTFspV/JZE89rapTNLg5EBDI/vPvM0S8vjO0Hhqm9QBRhp7DCbAAAAGF5Teioow3UOAG8oeV/pQi9gufRvkRzbqUeRalQlJyyo9xmFgdBqrq9k3ceOf/AF4qJfrJCCDebjdr1hFBfjDKrWXUEzRMhrGelXSGEPNQXH/YbaTwQMZ8Vq+WK3ZUHsInFQZDmI93n7n1y8u5HVe+SK6mxqtkAAEAAT1jjfLd6FiQM9d18iixF7BM8j/YbbDw0TRPTOdXoYyKbYDOKY8mV7Dn70JcWRvcDYW7qi/EMeTDiD91oNmp3Es6teaO3akNjPeCN3OpxasZjyO810HgAgFyVxUyO2h2E3WziWHIl+4+ef+ALhfgNrqQGRRgT+AO3mo3a7YShvhjetH09guYJE1641aKYZDwAoFwoFXI27yGwqcRBkOaj3efufWry0COq10dWO3WFq2s2AAAAAbwRjfOu1AESQoUYYVYfYRJCHupNGG48AKAg5ksFO/dK3yziQERC5rftff/olxdG77zVldSgCDu9/MGAUL8dkXCC5rnBg1AXj0LdmReK2O/zPNKXMDzrh1IqZXJy1bbjYzaDOAhS1S1M7j96/v7fLcb7SP2WX8ds1D6NYTRfDJdbGlFzh4jbt0YQiRDycJ8pxkNVVDGdMyZRvnE2vDgI0ny054P7npo8WNeV1KAIY17+YFBYpwURwNuhuZYSf5CAJnSQNefkzDMeAFAtV6SMaEtkbAOLgwAsuZKHvpTaUdeVLKPHbAAAABJe0DyhpXAZw6EQW3dyzTzjAQClfLEoFUyuzlXYwOIoIrm4577z9/9OMdZH1jvxjyKM6jEbAABAGJYKNc+CGh8gnsC6ExMUccA044GIUlaqlKyOjG1UcVwplf7PfOrUtr03BbjqwTHkSMQfXt9sAMD1STiGBwTq7QCXrplSQsjDffFBnynGg
|
|||
|
|
|||
|
<meta property="og:title" content="calliope mini - Blocks / Javascript editor - calliope" />
|
|||
|
<meta property="og:site_name" content="PXT" />
|
|||
|
<meta property="og:type" content="website" />
|
|||
|
<meta property="og:description" content="A Blocks / JavaScript code editor for the calliope mini." />
|
|||
|
<meta property="fb:app_id" content="" />
|
|||
|
<meta property="og:image" content="data:image/png;base64,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
|
|||
|
|
|||
|
<link rel="apple-touch-icon" href="data:image/png;base64,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
|
|||
|
<link rel="icon" type="image/png" href="data:image/png;base64,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
|
|||
|
<link rel="shortcut icon" href="data:image/png;base64,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
|
|||
|
<meta name="theme-color" content="#249899">
|
|||
|
<!-- end include meta.html -->
|
|||
|
|
|||
|
|
|||
|
<!-- include head.html -->
|
|||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
|||
|
<meta name="viewport" content="width=device-width,height=device-height,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0">
|
|||
|
|
|||
|
<link rel="stylesheet" href="/pxt-calliope/semantic.css" />
|
|||
|
<link rel="stylesheet" href="/pxt-calliope/docfiles/style.css" />
|
|||
|
<link rel="stylesheet" href="/pxt-calliope/docfiles/vs.css" />
|
|||
|
<link rel="stylesheet" href="/pxt-calliope/docfiles/target.css" />
|
|||
|
<link rel="stylesheet" href="/pxt-calliope/docfiles/fork.css" />
|
|||
|
|
|||
|
<script src="/pxt-calliope/jquery.js"></script>
|
|||
|
<script src="/pxt-calliope/semantic.js"></script>
|
|||
|
<script src="/pxt-calliope/lzma/lzma_worker-min.js"></script>
|
|||
|
|
|||
|
<script src="/pxt-calliope/embed.js" type="text/javascript"></script>
|
|||
|
<script src="/pxt-calliope/docfiles/docs.js" type="text/javascript"></script>
|
|||
|
<script src="/pxt-calliope/docfiles/target.js" type="text/javascript"></script>
|
|||
|
<script src="/pxt-calliope/docfiles/fork.js" type="text/javascript"></script>
|
|||
|
|
|||
|
<style>
|
|||
|
|
|||
|
.ui.accent { color: #249899; }
|
|||
|
.ui.inverted.accent { background: #249899; }
|
|||
|
|
|||
|
</style>
|
|||
|
|
|||
|
|
|||
|
<script>
|
|||
|
$(document).ready(function() {
|
|||
|
// patch youtube in semantic
|
|||
|
if ($ && $.fn && $.fn.embed && $.fn.embed.settings && $.fn.embed.settings.sources && $.fn.embed.settings.sources.youtube) {
|
|||
|
$.fn.embed.settings.sources.youtube.url = '//www.youtube.com/embed/{id}?rel=0'
|
|||
|
}
|
|||
|
$('.ui.embed').embed();
|
|||
|
})
|
|||
|
</script>
|
|||
|
<!-- end include head.html -->
|
|||
|
|
|||
|
|
|||
|
</head>
|
|||
|
|
|||
|
<body id='root' class='root'>
|
|||
|
|
|||
|
|
|||
|
<!-- include header.html -->
|
|||
|
<div class="ui fixed accent inverted menu">
|
|||
|
<div class="ui container">
|
|||
|
<a href="/pxt-calliope/docs/.html" class="header item">
|
|||
|
<img class="ui mini image" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxOC4wLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4KCjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHZlcnNpb249IjEuMSIKICAgaWQ9IkViZW5lXzEiCiAgIHg9IjBweCIKICAgeT0iMHB4IgogICB2aWV3Qm94PSIwIDAgMTc1LjQ5OTk5IDE3Mi40IgogICBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA4NDEuOSA1OTUuMyIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIKICAgaW5rc2NhcGU6dmVyc2lvbj0iMC45MSByMTM3MjUiCiAgIHNvZGlwb2RpOmRvY25hbWU9IkxvZ29fQ2FsbGlvcGVfV29tYW4uc3ZnIgogICB3aWR0aD0iMTc1LjUiCiAgIGhlaWdodD0iMTcyLjM5OTk5Ij48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE1MDExIj48cmRmOlJERj48Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjxkYzp0aXRsZT48L2RjOnRpdGxlPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcwogICAgIGlkPSJkZWZzNTAwOSIgLz48c29kaXBvZGk6bmFtZWR2aWV3CiAgICAgcGFnZWNvbG9yPSIjZmZmZmZmIgogICAgIGJvcmRlcmNvbG9yPSIjNjY2NjY2IgogICAgIGJvcmRlcm9wYWNpdHk9IjEiCiAgICAgb2JqZWN0dG9sZXJhbmNlPSIxMCIKICAgICBncmlkdG9sZXJhbmNlPSIxMCIKICAgICBndWlkZXRvbGVyYW5jZT0iMTAiCiAgICAgaW5rc2NhcGU6cGFnZW9wYWNpdHk9IjAiCiAgICAgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIKICAgICBpbmtzY2FwZTp3aW5kb3ctd2lkdGg9IjE5MjAiCiAgICAgaW5rc2NhcGU6d2luZG93LWhlaWdodD0iMTEzNyIKICAgICBpZD0ibmFtZWR2aWV3NTAwNyIKICAgICBzaG93Z3JpZD0iZmFsc2UiCiAgICAgaW5rc2NhcGU6em9vbT0iMC4zNDIwODMzNyIKICAgICBpbmtzY2FwZTpjeD0iNDIwLjk1MDAxIgogICAgIGlua3NjYXBlOmN5PSIyOTcuNjQ5OTkiCiAgICAgaW5rc2NhcGU6d2luZG93LXg9Ii04IgogICAgIGlua3NjYXBlOndpbmRvdy15PSIxNTYiCiAgICAgaW5rc2NhcGU6d2luZG93LW1heGltaXplZD0iMSIKICAgICBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJFYmVuZV8xIiAvPjxnCiAgICAgaWQ9Imc0OTU1IgogICAgIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yNjAuOTAwMjUsLTIwNC4xKSI+PGcKICAgICAgIGlkPSJnNDk1NyI+PGRlZnMKICAgICAgICAgaWQ9ImRlZnM0OTU5Ij48cmVjdAogICAgICAgICAgIGlkPSJTVkdJRF83XyIKICAgICAgICAgICB4PSIxOTMuMTAwMDEiCiAgICAgICAgICAgeT0iMjA0LjEwMDAxIgogICAgICAgICAgIHdpZHRoPSIzMTguMjk5OTkiCiAgICAgICAgICAgaGVpZ2h0PSIyNTYuMjk5OTkiIC8+PC9kZWZzPjxjbGlwUGF0aAogICAgICAgICBpZD0iU1ZHSURfMV8iPjx1c2UKICAgICAgICAgICB4bGluazpocmVmPSIjU1ZHSURfN18iCiAgICAgICAgICAgb3ZlcmZsb3c9InZpc2libGUiCiAgICAgICAgICAgaWQ9InVzZTQ5NjMiCiAgICAgICAgICAgc3R5bGU9Im92ZXJmbG93OnZpc2libGUiCiAgICAgICAgICAgeD0iMCIKICAgICAgICAgICB5PSIwIgogICAgICAgICAgIHdpZHRoPSIxMDAlIgogICAgICAgICAgIGhlaWdodD0iMTAwJSIgLz48L2NsaXBQYXRoPjwvZz48ZwogICAgICAgaWQ9Imc0OTY1Ij48ZGVmcwogICAgICAgICBpZD0iZGVmczQ5NjciPjxyZWN0CiAgICAgICAgICAgaWQ9IlNWR0lEXzlfIgogICAgICAgICAgIHg9IjE5My4xMDAwMSIKICAgICAgICAgICB5PSIyMDQuMTAwMDEiCiAgICAgICAgICAgd2lkdGg9IjMxOC4yOTk5OSIKICAgICAgICAgICBoZWlnaHQ9IjI1Ni4yOTk5OSIgLz48L2RlZnM+PGNsaXBQYXRoCiAgICAgICAgIGlkPSJTVkdJRF8yXyI+PHVzZQogICAgICAgICAgIHhsaW5rOmhyZWY9IiNTVkdJRF85XyIKICAgICAgICAgICBvdmVyZmxvdz0idmlzaWJsZSIKICAgICAgICAgICBpZD0idXNlNDk3MSIKICAgICAgICAgICBzdHlsZT0ib3ZlcmZsb3c6dmlzaWJsZSIKICAgICAgICAgICB4PSIwIgogICAgICAgICAgIHk9IjAiCiAgICAgICAgICAgd2lkdGg9IjEwMCUiCiAgICAgICAgICAgaGVpZ2h0PSIxMDAlIiAvPjwvY2xpcFBhdGg+PC9nPjxnCiAgICAgICBpZD0iZzQ5NzMiPjxkZWZzCiAgICAgICAgIGlkPSJkZWZzNDk3NSI+PHJlY3QKICAgICAgICAgICBpZD0iU1ZHSURfMTFfIgogICAgICAgICAgIHg9IjE5My4xMDAwMSIKICAgICAgICAgICB5PSIyMDQuMTAwMDEiCiAgICAgICAgICAgd2lkdGg9IjMxOC4yOTk5OSIKICAgICAgICAgICBoZWlnaHQ9IjI1Ni4yOTk5OSIgLz48L2RlZnM+PGNsaXBQYXRoCiAgICAgICAgIGlkPSJTVkdJRF8zXyI+PHVzZQogICAgICAgICAgIHhsaW5rOmhyZWY9IiNTVkdJRF8xMV8iCiAgICAgICAgICAgb3ZlcmZsb3c9InZpc2libGUiCiAgICAgICAgICAgaWQ9InVzZTQ5NzkiCiAgICAgICAgICAgc3R5bGU9Im92ZXJmbG93OnZpc
|
|||
|
</a>
|
|||
|
<!-- Menu -->
|
|||
|
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
<!-- end include header.html -->
|
|||
|
|
|||
|
|
|||
|
<div id="docs" class="ui main container mainbody">
|
|||
|
|
|||
|
<div class="ui breadcrumb">
|
|||
|
<a class=" section"
|
|||
|
href="/pxt-calliope/docs/js.html">js</a><i class="right chevron icon divider"></i><a class="active section"
|
|||
|
href="/pxt-calliope/docs/js/classes.md.html">classes.md</a>
|
|||
|
</div>
|
|||
|
|
|||
|
<div class="ui text">
|
|||
|
<h1 id="classes">Classes</h1>
|
|||
|
<p>Traditional JavaScript focuses on functions and prototype-based inheritance as the basic means of building up reusable components,
|
|||
|
but this may feel a bit awkward to programmers more comfortable with an object-oriented approach, where classes inherit functionality
|
|||
|
and objects are built from these classes.</p>
|
|||
|
<p>Starting with ECMAScript 2015, also known as ECMAScript 6, JavaScript programmers will be able to build their applications using
|
|||
|
this object-oriented class-based approach. TypeScript, allows you to use these techniques now, compiling them
|
|||
|
down to JavaScript that works across all major browsers and platforms, without having to wait for the next version of JavaScript.</p>
|
|||
|
<p>Let’s take a look at a simple class-based example:</p>
|
|||
|
<pre><code class="lang-ts"><span class="hljs-keyword">class</span> Greeter {
|
|||
|
greeting: <span class="hljs-built_in">string</span>;
|
|||
|
<span class="hljs-keyword">constructor</span>(<span class="hljs-params">message: <span class="hljs-built_in">string</span></span>) {
|
|||
|
<span class="hljs-keyword">this</span>.greeting = message;
|
|||
|
}
|
|||
|
greet() {
|
|||
|
<span class="hljs-keyword">return</span> <span class="hljs-string">"Hello, "</span> + <span class="hljs-keyword">this</span>.greeting;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
<span class="hljs-keyword">let</span> greeter = <span class="hljs-keyword">new</span> Greeter(<span class="hljs-string">"world"</span>);</code></pre>
|
|||
|
<p>We declare a new class <code>Greeter</code>. This class has three members: a property called <code>greeting</code>, a constructor, and a method <code>greet</code>.</p>
|
|||
|
<p>You’ll notice that in the class when we refer to one of the members of the class we prepend <code>this.</code>.
|
|||
|
This denotes that it’s a member access.</p>
|
|||
|
<p>In the last line we construct an instance of the <code>Greeter</code> class using <code>new</code>.
|
|||
|
This calls into the constructor we defined earlier, creating a new object with the <code>Greeter</code> shape, and running the constructor to initialize it.</p>
|
|||
|
<h1 id="inheritance">Inheritance</h1>
|
|||
|
|
|||
|
<div class="ui info message">
|
|||
|
<div class="content">
|
|||
|
|
|||
|
<h3 id="inheritance-is-not-supported-yet-for-the-calliope-mini-coming-soon-">Inheritance is not supported yet for the Calliope mini. Coming soon…</h3>
|
|||
|
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
<p>In TypeScript, we can use common object-oriented patterns.
|
|||
|
Of course, one of the most fundamental patterns in class-based programming is being able to extend existing classes to create new ones using inheritance.</p>
|
|||
|
<p>Let’s take a look at an example:</p>
|
|||
|
<pre><code class="lang-ts-ignore"><span class="hljs-keyword">class</span> Animal {
|
|||
|
name: <span class="hljs-built_in">string</span>;
|
|||
|
<span class="hljs-keyword">constructor</span>(<span class="hljs-params">theName: <span class="hljs-built_in">string</span></span>) { <span class="hljs-keyword">this</span>.name = theName; }
|
|||
|
move(distanceInMeters: <span class="hljs-built_in">number</span> = <span class="hljs-number">0</span>) {
|
|||
|
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${this.name}</span> moved <span class="hljs-subst">${distanceInMeters}</span>m.`</span>);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
<span class="hljs-keyword">class</span> Snake <span class="hljs-keyword">extends</span> Animal {
|
|||
|
<span class="hljs-keyword">constructor</span>(<span class="hljs-params">name: <span class="hljs-built_in">string</span></span>) { <span class="hljs-keyword">super</span>(name); }
|
|||
|
move(distanceInMeters = <span class="hljs-number">5</span>) {
|
|||
|
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Slithering..."</span>);
|
|||
|
<span class="hljs-keyword">super</span>.move(distanceInMeters);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
<span class="hljs-keyword">class</span> Horse <span class="hljs-keyword">extends</span> Animal {
|
|||
|
<span class="hljs-keyword">constructor</span>(<span class="hljs-params">name: <span class="hljs-built_in">string</span></span>) { <span class="hljs-keyword">super</span>(name); }
|
|||
|
move(distanceInMeters = <span class="hljs-number">45</span>) {
|
|||
|
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Galloping..."</span>);
|
|||
|
<span class="hljs-keyword">super</span>.move(distanceInMeters);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
<span class="hljs-keyword">let</span> sam = <span class="hljs-keyword">new</span> Snake(<span class="hljs-string">"Sammy the Python"</span>);
|
|||
|
<span class="hljs-keyword">let</span> tom: Animal = <span class="hljs-keyword">new</span> Horse(<span class="hljs-string">"Tommy the Palomino"</span>);
|
|||
|
|
|||
|
sam.move();
|
|||
|
tom.move(<span class="hljs-number">34</span>);</code></pre>
|
|||
|
<p>This example covers quite a few of the inheritance features in TypeScript that are common to other languages.
|
|||
|
Here we see the <code>extends</code> keywords used to create a subclass.
|
|||
|
You can see this where <code>Horse</code> and <code>Snake</code> subclass the base class <code>Animal</code> and gain access to its features.</p>
|
|||
|
<p>Derived classes that contain constructor functions must call <code>super()</code> which will execute the constructor function on the base class.</p>
|
|||
|
<p>The example also shows how to override methods in the base class with methods that are specialized for the subclass.
|
|||
|
Here both <code>Snake</code> and <code>Horse</code> create a <code>move</code> method that overrides the <code>move</code> from <code>Animal</code>, giving it functionality specific to each class.
|
|||
|
Note that even though <code>tom</code> is declared as an <code>Animal</code>, since its value is a <code>Horse</code>, when <code>tom.move(34)</code> calls the overriding method in <code>Horse</code>:</p>
|
|||
|
<pre><code class="lang-Text">Slithering...
|
|||
|
Sammy the Python moved 5m.
|
|||
|
Galloping...
|
|||
|
Tommy the Palomino moved 34m.</code></pre>
|
|||
|
<h1 id="public-private-and-protected-modifiers">Public, private, and protected modifiers</h1>
|
|||
|
<h2 id="public-by-default">Public by default</h2>
|
|||
|
<p>In our examples, we’ve been able to freely access the members that we declared throughout our programs.
|
|||
|
If you’re familiar with classes in other languages, you may have noticed in the above examples
|
|||
|
we haven’t had to use the word <code>public</code> to accomplish this; for instance,
|
|||
|
C# requires that each member be explicitly labeled <code>public</code> to be visible.
|
|||
|
In TypeScript, each member is <code>public</code> by default.</p>
|
|||
|
<p>You may still mark a member <code>public</code> explicitly.
|
|||
|
We could have written the <code>Animal</code> class from the previous section in the following way:</p>
|
|||
|
<pre><code class="lang-ts-ignore"><span class="hljs-keyword">class</span> Animal {
|
|||
|
<span class="hljs-keyword">public</span> name: <span class="hljs-built_in">string</span>;
|
|||
|
<span class="hljs-keyword">public</span> <span class="hljs-keyword">constructor</span>(<span class="hljs-params">theName: <span class="hljs-built_in">string</span></span>) { <span class="hljs-keyword">this</span>.name = theName; }
|
|||
|
<span class="hljs-keyword">public</span> move(distanceInMeters: <span class="hljs-built_in">number</span>) {
|
|||
|
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${this.name}</span> moved <span class="hljs-subst">${distanceInMeters}</span>m.`</span>);
|
|||
|
}
|
|||
|
}</code></pre>
|
|||
|
<h2 id="understanding-private-">Understanding <code>private</code></h2>
|
|||
|
<p>When a member is marked <code>private</code>, it cannot be accessed from outside of its containing class. For example:</p>
|
|||
|
<pre><code class="lang-ts-ignore"><span class="hljs-keyword">class</span> Animal {
|
|||
|
<span class="hljs-keyword">private</span> name: <span class="hljs-built_in">string</span>;
|
|||
|
<span class="hljs-keyword">constructor</span>(<span class="hljs-params">theName: <span class="hljs-built_in">string</span></span>) { <span class="hljs-keyword">this</span>.name = theName; }
|
|||
|
}
|
|||
|
|
|||
|
<span class="hljs-keyword">new</span> Animal(<span class="hljs-string">"Cat"</span>).name; <span class="hljs-comment">// Error: 'name' is private;</span></code></pre>
|
|||
|
<p>TypeScript is a structural type system.
|
|||
|
When we compare two different types, regardless of where they came from, if the types of all members are compatible, then we say the types themselves are compatible.</p>
|
|||
|
<p>However, when comparing types that have <code>private</code> and <code>protected</code> members, we treat these types differently.
|
|||
|
For two types to be considered compatible, if one of them has a <code>private</code> member,
|
|||
|
then the other must have a <code>private</code> member that originated in the same declaration.
|
|||
|
The same applies to <code>protected</code> members.</p>
|
|||
|
<p>Let’s look at an example to better see how this plays out in practice:</p>
|
|||
|
<pre><code class="lang-ts-ignore"><span class="hljs-keyword">class</span> Animal {
|
|||
|
<span class="hljs-keyword">private</span> name: <span class="hljs-built_in">string</span>;
|
|||
|
<span class="hljs-keyword">constructor</span>(<span class="hljs-params">theName: <span class="hljs-built_in">string</span></span>) { <span class="hljs-keyword">this</span>.name = theName; }
|
|||
|
}
|
|||
|
|
|||
|
<span class="hljs-keyword">class</span> Rhino <span class="hljs-keyword">extends</span> Animal {
|
|||
|
<span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) { <span class="hljs-keyword">super</span>(<span class="hljs-string">"Rhino"</span>); }
|
|||
|
}
|
|||
|
|
|||
|
<span class="hljs-keyword">class</span> Employee {
|
|||
|
<span class="hljs-keyword">private</span> name: <span class="hljs-built_in">string</span>;
|
|||
|
<span class="hljs-keyword">constructor</span>(<span class="hljs-params">theName: <span class="hljs-built_in">string</span></span>) { <span class="hljs-keyword">this</span>.name = theName; }
|
|||
|
}
|
|||
|
|
|||
|
<span class="hljs-keyword">let</span> animal = <span class="hljs-keyword">new</span> Animal(<span class="hljs-string">"Goat"</span>);
|
|||
|
<span class="hljs-keyword">let</span> rhino = <span class="hljs-keyword">new</span> Rhino();
|
|||
|
<span class="hljs-keyword">let</span> employee = <span class="hljs-keyword">new</span> Employee(<span class="hljs-string">"Bob"</span>);
|
|||
|
|
|||
|
animal = rhino;
|
|||
|
animal = employee; <span class="hljs-comment">// Error: 'Animal' and 'Employee' are not compatible</span></code></pre>
|
|||
|
<p>In this example, we have an <code>Animal</code> and a <code>Rhino</code>, with <code>Rhino</code> being a subclass of <code>Animal</code>.
|
|||
|
We also have a new class <code>Employee</code> that looks identical to <code>Animal</code> in terms of shape.
|
|||
|
We create some instances of these classes and then try to assign them to each other to see what will happen.
|
|||
|
Because <code>Animal</code> and <code>Rhino</code> share the <code>private</code> side of their shape from the same declaration of
|
|||
|
<code>private name: string</code> in <code>Animal</code>, they are compatible. However, this is not the case for <code>Employee</code>.
|
|||
|
When we try to assign from an <code>Employee</code> to <code>Animal</code> we get an error that these types are not compatible.
|
|||
|
Even though <code>Employee</code> also has a <code>private</code> member called <code>name</code>, it’s not the one we declared in <code>Animal</code>.</p>
|
|||
|
<h2 id="understanding-protected-">Understanding <code>protected</code></h2>
|
|||
|
<p>The <code>protected</code> modifier acts much like the <code>private</code> modifier with the exception that members
|
|||
|
declared <code>protected</code> can also be accessed by instances of deriving classes. For example,</p>
|
|||
|
<pre><code class="lang-ts-ignore"><span class="hljs-keyword">class</span> Person {
|
|||
|
<span class="hljs-keyword">protected</span> name: <span class="hljs-built_in">string</span>;
|
|||
|
<span class="hljs-keyword">constructor</span>(<span class="hljs-params">name: <span class="hljs-built_in">string</span></span>) { <span class="hljs-keyword">this</span>.name = name; }
|
|||
|
}
|
|||
|
|
|||
|
<span class="hljs-keyword">class</span> Employee <span class="hljs-keyword">extends</span> Person {
|
|||
|
<span class="hljs-keyword">private</span> department: <span class="hljs-built_in">string</span>;
|
|||
|
|
|||
|
<span class="hljs-keyword">constructor</span>(<span class="hljs-params">name: <span class="hljs-built_in">string</span>, department: <span class="hljs-built_in">string</span></span>) {
|
|||
|
<span class="hljs-keyword">super</span>(name);
|
|||
|
<span class="hljs-keyword">this</span>.department = department;
|
|||
|
}
|
|||
|
|
|||
|
<span class="hljs-keyword">public</span> getElevatorPitch() {
|
|||
|
<span class="hljs-keyword">return</span> <span class="hljs-string">`Hello, my name is <span class="hljs-subst">${this.name}</span> and I work in <span class="hljs-subst">${this.department}</span>.`</span>;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
<span class="hljs-keyword">let</span> howard = <span class="hljs-keyword">new</span> Employee(<span class="hljs-string">"Howard"</span>, <span class="hljs-string">"Sales"</span>);
|
|||
|
<span class="hljs-built_in">console</span>.log(howard.getElevatorPitch());
|
|||
|
<span class="hljs-built_in">console</span>.log(howard.name); <span class="hljs-comment">// error</span></code></pre>
|
|||
|
<p>Notice that while we can’t use <code>name</code> from outside of <code>Person</code>,
|
|||
|
we can still use it from within an instance method of <code>Employee</code> because <code>Employee</code> derives from <code>Person</code>.</p>
|
|||
|
<p>A constructor may also be marked <code>protected</code>.
|
|||
|
This means that the class cannot be instantiated outside of its containing class, but can be extended. For example,</p>
|
|||
|
<pre><code class="lang-ts-ignore"><span class="hljs-keyword">class</span> Person {
|
|||
|
<span class="hljs-keyword">protected</span> name: <span class="hljs-built_in">string</span>;
|
|||
|
<span class="hljs-keyword">protected</span> <span class="hljs-keyword">constructor</span>(<span class="hljs-params">theName: <span class="hljs-built_in">string</span></span>) { <span class="hljs-keyword">this</span>.name = theName; }
|
|||
|
}
|
|||
|
|
|||
|
<span class="hljs-comment">// Employee can extend Person</span>
|
|||
|
<span class="hljs-keyword">class</span> Employee <span class="hljs-keyword">extends</span> Person {
|
|||
|
<span class="hljs-keyword">private</span> department: <span class="hljs-built_in">string</span>;
|
|||
|
|
|||
|
<span class="hljs-keyword">constructor</span>(<span class="hljs-params">name: <span class="hljs-built_in">string</span>, department: <span class="hljs-built_in">string</span></span>) {
|
|||
|
<span class="hljs-keyword">super</span>(name);
|
|||
|
<span class="hljs-keyword">this</span>.department = department;
|
|||
|
}
|
|||
|
|
|||
|
<span class="hljs-keyword">public</span> getElevatorPitch() {
|
|||
|
<span class="hljs-keyword">return</span> <span class="hljs-string">`Hello, my name is <span class="hljs-subst">${this.name}</span> and I work in <span class="hljs-subst">${this.department}</span>.`</span>;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
<span class="hljs-keyword">let</span> howard = <span class="hljs-keyword">new</span> Employee(<span class="hljs-string">"Howard"</span>, <span class="hljs-string">"Sales"</span>);
|
|||
|
<span class="hljs-keyword">let</span> john = <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"John"</span>); <span class="hljs-comment">// Error: The 'Person' constructor is protected</span></code></pre>
|
|||
|
<h1 id="readonly-modifier">Readonly modifier</h1>
|
|||
|
<p>You can make properties readonly by using the <code>readonly</code> keyword.
|
|||
|
Readonly properties must be initialized at their declaration or in the constructor.</p>
|
|||
|
<pre><code class="lang-ts-ignore"><span class="hljs-keyword">class</span> Octopus {
|
|||
|
readonly name: <span class="hljs-built_in">string</span>;
|
|||
|
readonly numberOfLegs: <span class="hljs-built_in">number</span> = <span class="hljs-number">8</span>;
|
|||
|
<span class="hljs-keyword">constructor</span> (<span class="hljs-params">theName: <span class="hljs-built_in">string</span></span>) {
|
|||
|
<span class="hljs-keyword">this</span>.name = theName;
|
|||
|
}
|
|||
|
}
|
|||
|
<span class="hljs-keyword">let</span> dad = <span class="hljs-keyword">new</span> Octopus(<span class="hljs-string">"Man with the 8 strong legs"</span>);
|
|||
|
dad.name = <span class="hljs-string">"Man with the 3-piece suit"</span>; <span class="hljs-comment">// error! name is readonly.</span></code></pre>
|
|||
|
<h2 id="parameter-properties">Parameter properties</h2>
|
|||
|
<p>In our last example, we had to declare a readonly member <code>name</code> and a constructor parameter <code>theName</code> in the <code>Octopus</code> class, and we then immediately set <code>name</code> to <code>theName</code>.
|
|||
|
This turns out to be a very common practice.
|
|||
|
<em>Parameter properties</em> let you create and initialize a member in one place.
|
|||
|
Here’s a further revision of the previous <code>Octopus</code> class using a parameter property:</p>
|
|||
|
<pre><code class="lang-ts-ignore"><span class="hljs-keyword">class</span> Octopus {
|
|||
|
readonly numberOfLegs: <span class="hljs-built_in">number</span> = <span class="hljs-number">8</span>;
|
|||
|
<span class="hljs-keyword">constructor</span>(<span class="hljs-params">readonly name: <span class="hljs-built_in">string</span></span>) {
|
|||
|
}
|
|||
|
}</code></pre>
|
|||
|
<p>Notice how we dropped <code>theName</code> altogether and just use the shortened <code>readonly name: string</code> parameter on the constructor to create and initialize the <code>name</code> member.
|
|||
|
We’ve consolidated the declarations and assignment into one location.</p>
|
|||
|
<p>Parameter properties are declared by prefixing a constructor parameter with an accessibility modifier or <code>readonly</code>, or both.
|
|||
|
Using <code>private</code> for a parameter property declares and initializes a private member; likewise, the same is done for <code>public</code>, <code>protected</code>, and <code>readonly</code>.</p>
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
<p style="margin-top:1em"><a href="https://github.com/Microsoft/pxt-calliope/blob/master/docs/docs/js/classes.md"><i class="write icon"></i>Edit this page on GitHub</a></p>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
<!-- include footer.html -->
|
|||
|
<div class="ui inverted accent vertical footer segment">
|
|||
|
<div class="ui center aligned container">
|
|||
|
<div class="ui horizontal inverted small divided link list">
|
|||
|
<a class="item" href="https://www.pxt.io/" title="Programming Experience Toolkit">Powered by PXT</a>
|
|||
|
<a class="item" href="https://www.pxt.io/contact">Contact Us</a>
|
|||
|
<a class="item" href="https://www.pxt.io/privacy">Privacy & Cookies</a>
|
|||
|
<a class="item" href="https://www.pxt.io/legal">Terms Of Use</a>
|
|||
|
<a class="item" href="https://www.pxt.io/trademarks">Trademarks</a>
|
|||
|
<div class="item">© 2016 Microsoft</div>
|
|||
|
<!-- we need to force the browser to load this font -->
|
|||
|
<div style='font-family: Icons; color: #010101;' aria-hidden="true">.</div>
|
|||
|
</div>
|
|||
|
<a class="item" href="https://www.microsoft.com/"><img class="ui centered image" src="https://az851932.vo.msecnd.net/pub/pmapoirq" /></a>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
<!-- end include footer.html -->
|
|||
|
|
|||
|
|
|||
|
<!-- include macros.html -->
|
|||
|
<!-- macro button -->
|
|||
|
|
|||
|
<!-- macro vimeo -->
|
|||
|
|
|||
|
<!-- macro youtube -->
|
|||
|
|
|||
|
<!-- macro section -->
|
|||
|
|
|||
|
<!-- macro hide -->
|
|||
|
|
|||
|
<!-- macro avatar -->
|
|||
|
|
|||
|
<!-- macro hint -->
|
|||
|
|
|||
|
<!-- wrapped around ordinary content -->
|
|||
|
<!-- macro main-container -->
|
|||
|
|
|||
|
<!-- used for 'column' box - they are collected and wrapped in 'column-container' -->
|
|||
|
<!-- macro column -->
|
|||
|
<!-- macro column-container -->
|
|||
|
|
|||
|
|
|||
|
<!-- Menu on the top of the page -->
|
|||
|
<!-- macro item -->
|
|||
|
|
|||
|
<!-- macro divider -->
|
|||
|
|
|||
|
<!-- macro top-dropdown -->
|
|||
|
|
|||
|
<!-- macro inner-dropdown -->
|
|||
|
|
|||
|
|
|||
|
<!-- end include macros.html -->
|
|||
|
|
|||
|
|
|||
|
<!-- include tracking.html -->
|
|||
|
<script type="text/javascript">
|
|||
|
var appInsights=window.appInsights||function(config){
|
|||
|
function i(config){t[config]=function(){var i=arguments;t.queue.push(function(){t[config].apply(t,i)})}}var t={config:config},u=document,e=window,o="script",s="AuthenticatedUserContext",h="start",c="stop",l="Track",a=l+"Event",v=l+"Page",y=u.createElement(o),r,f;y.src=config.url||"https://az416426.vo.msecnd.net/scripts/a/ai.0.js";u.getElementsByTagName(o)[0].parentNode.appendChild(y);try{t.cookie=u.cookie}catch(p){}for(t.queue=[],t.version="1.0",r=["Event","Exception","Metric","PageView","Trace","Dependency"];r.length;)i("track"+r.pop());return i("set"+s),i("clear"+s),i(h+a),i(c+a),i(h+v),i(c+v),i("flush"),config.disableExceptionTracking||(r="onerror",i("_"+r),f=e[r],e[r]=function(config,i,u,e,o){var s=f&&f(config,i,u,e,o);return s!==!0&&t["_"+r](config,i,u,e,o),s}),t
|
|||
|
}({
|
|||
|
instrumentationKey:"9801ed01-c40f-46ec-aa40-2a1742a9e71c",
|
|||
|
disableAjaxTracking: true,
|
|||
|
overridePageViewDuration: false,
|
|||
|
disableExceptionTracking: true,
|
|||
|
isCookieUseDisabled: true,
|
|||
|
isStorageUseDisabled: true
|
|||
|
});
|
|||
|
window.appInsights=appInsights;
|
|||
|
appInsights.queue.push(function () {
|
|||
|
appInsights.context.addTelemetryInitializer(function (envelope) {
|
|||
|
if (typeof pxtConfig === "undefined") return;
|
|||
|
var telemetryItem = envelope.data.baseData;
|
|||
|
telemetryItem.properties = telemetryItem.properties || {};
|
|||
|
telemetryItem.properties["target"] = pxtConfig.targetId;
|
|||
|
telemetryItem.properties["version"] = pxtConfig.targetVersion;
|
|||
|
telemetryItem.properties["stage"] = (pxtConfig.relprefix || "/--").replace(/[^a-z]/ig, '')
|
|||
|
if (typeof window !== "undefined" && window.location && /[?&]electron=1/i.test(window.location.href))
|
|||
|
telemetryItem.properties["electron"] = 1;
|
|||
|
});
|
|||
|
});
|
|||
|
appInsights.trackPageView();
|
|||
|
</script>
|
|||
|
<!-- end include tracking.html -->
|
|||
|
|
|||
|
|
|||
|
</body>
|
|||
|
|
|||
|
</html>
|