学习笔记:MDN的JavaScript

JavaScript 第一步javascript

什么是JavaScripthtml

每次当你浏览网页时不仅是显示静态信息—— 显示即时更新的内容, 或者交互式的地图,或 2D/3D 图形动画,又或者自动播放视频等,你能够确信,JavaScript 参与其中。java

HTML是一种标记语言,用来结构化咱们的网页内容和赋予内容含义,例如定义段落、标题、和数据表,或在页面中嵌入图片和视频。node

CSS 是一种样式规则语言,咱们将样式应用于咱们的 HTML 内容, 例如设置背景颜色和字体,在多个列中布局咱们的内容。git

JavaScript 是一种编程语言,容许你建立动态更新的内容,控制多媒体,图像动画,和一些其余的东西。好吧,虽然不是一切,可是它的神奇之处是你可以用几行JavaScript代码就能实现。程序员

JavaScript 语言的核心包含一些广泛的编程特色,以让你能够作到以下的事情:github

  • 在变量中储存有用的值。好比,咱们用prompt请求输入一个新的名字,而后把那个名字储存到一个叫 name 的变量.
  • 对一段文本(在编程中被称为“字符串”)进行操做。在上面的例子中,咱们取出字符串 "Player 1: ",而后把它和 name 变量连结起来,创造出完整的文本标签,例:''Player 1: Chris"。
  • 运行代码以响应在网页中发生的特定事件。在上述的例子中,咱们用了一个 click 事件来检测按钮何时被点击,而后运行更新文本标签的代码。
  • 以及更多!

然而更使人兴奋的是创建在 JavaScript 语言的核心之上的功能。在你的 JavaScript 代码里,被称为应用程序编程接口 [Application Programming Interfaces (APIs)] 的功能会提供额外的超能力给你使用。web

APIs 是已经创建好的一套代码组件,目的是让开发者能够实现除了用APIs以外很难甚至不可能实现的程序。它们的做用就像是已经制做好的家具套件对家居建设的做用同样——从一堆已经切好的木板开始组装一个书柜,显然比本身设计,寻找合适的木材,裁切至合适的大小和形状,找到合适大小的螺丝钉,而后组装成一个书柜要简单得多。正则表达式

APIs一般分红两个分类:chrome

浏览器 APIs (Browser APIs) 已经安装在你的浏览器中,并且可以从周围的计算机环境中揭露数据,或者作有用的复琐事情。举个例子:

  • 文档对象模型 API [DOM (Document Object Model) API] 容许你操做 HTML 和 CSS,建立,移除和修改 HTML,动态地应用新的样式到你的页面,等等。好比说每次你在一个页面里看到一个弹出窗口,或者显示一些新的内容,这就是 DOM 在运做。
  • 地理定位 API [Geolocation API] 获取地理信息。这就是为何谷歌地图能够找到你的位置,并且标示在地图上。
  • 画布 [Canvas] 和 WebGL APIs 容许你建立生动的 2D 和 3D 图像。人们正运用这些网页技术进行一些使人惊叹的事情——好比说 Chrome Experiments 和 webglsamples
  • 音像和影像 APIs [Audio and Video APIs],像 HTMLMediaElement 和 WebRTC 容许你运用多媒体去作一些很是有趣的事情,好比在网页中播放音像和影像,或者从你的网页摄像头中获取获取录像,而后在其余人的电脑上展现。

第三方 APIs (Third party APIs)(这些 APIs 是高级的) 默认是没有安装到浏览器中的,而你一般须要从网络上的某些地方取得它们的代码和信息。举个例子:

  • 推特 API [Twitter API] 容许你作一些像是在你的网站上展现你的最新推送之类的事情。
  • 谷歌地图 API [Google Maps API] 容许你去嵌入定制的地图到你的网站,和其余的功能。

在 HTML 和 CSS 已经被集合和组装成一个网页后,浏览器的 JavaScript 引擎执行 JavaScript。这保证了当 JavaScript 开始运行时,网页的结构和样式已经在该出现的地方了。这是一个好事情,正如 JavaScript 的广泛用处是经过 DOM API(如以前说起的那样)动态地修改 HTML 和 CSS 来更新用户交界面。若是 JavaScript 在 HTML 和 CSS 加载完成以前加载运行,那么会发生错误。

每一个浏览器标签自己就是一个用来运行代码的分离的容器(这些容器用专业术语称为“运行环境”)——这意味着在大多数状况中,每一个标签中的代码是彻底分离地运行,并且在一个标签中的代码不能直接影响在另外一个标签中的代码——或者在另外一个网站中的。这是一个好的安全措施——若是不是这样的话,那么海盗们就能够开始写从其余网站偷取信息的代码,和其余像这样的坏事。注意:有安全的方式去在不一样网站/标签中传送代码和数据,但这些方法是高级的技术。

当浏览器遇到一块 JavaScript 代码时,它一般会按顺序运行这代码块,从上往下。这意味着你须要注意你放置代码的顺序。

在编程环境中,你或许据说过这两个术语 解释 [interpreted] 和 编译 [compiled]。JavaScript 是一个解释语言——代码从上到下运行,而运行的结果会立刻被返回。在浏览器运行代码前,你没必要先把它转化为其余形式。另外一方面来讲,编译语言则须要在运行前转化为另外一种形式。好比说 C/C++ 则要先被编译成汇编语言,而后再由电脑运行。

客户端[client-side]代码是在用户的电脑上运行的代码——当浏览一个网页时,这个网页的客户端代码就会被下载,而后由浏览器来运行和展现。在另外一方面,服务器端[server-side]代码则在服务器上运行,而后它的结果会由浏览器进行下载和展现。JavaScript也是流行的服务器端网页语言!JavaScript 同时也能用做服务器端语言,好比说在流行的 Node.js 环境中。

JavaScript 是区分大小写的,并且很是的讲究。

把 JavaScript 放置在一个外部文件中,对于规划你的代码来讲,这一般是一件好事,让它能够在多个 HTML 文件中重复使用,再加上 HTML 中没有一大堆脚本的话,HTML 会更容易阅读。请不要内联JavaScriptHTML这是一个用 JavaScript 来污染你的 HTML 的坏实践,并且它还不高效——你会须要在每一个想要 JavaScript 应用到的按钮上包含 onclick="createParagraph()" 属性使用一个纯 JavaScript 结构容许你使用一个指令来应用于全部的按钮,不管页面上有多少个,和有多少个按钮被添加或者移除。不须要对 JavaScript 进行任何修改。

JavaScript的注释方式和C++同样,有两种(CSS只有C++的其中一种,HTML也是一种,但和C++的不同)。

进入JavaScript的第一课

像程序员同样思考。

您可使用关键字var以及变量的名称建立一个变量。

函数Window.alert:即警告。弹出警告窗口。

===:Strict equality (is it exactly the same?)

!==:Non-equality (is it not the same?)

您可能会看到有些人在他们的代码中使用==和!=来平等和不相等,这些都是JavaScript中的有效运算符,但它们与===/!==不一样,前者测试值是否相同, 可是数据类型可能不一样,然后者的严格版本测试值和数据类型是否相同。 严格的版本每每致使更少的错误,因此咱们建议您使用这些严格的版本。

小于等于和大于等于都只有一个等号,而不是两个。

事件(Events)是浏览器中发生的动做,例如点击按钮,加载页面或播放视频,咱们能够调用代码来响应。侦听事件发生的构造方法称为事件监听器,响应事件触发而运行的代码块被称为事件处理器

注意,当函数做为事件监听方法的参数时,函数名后不该带括号。

In JavaScript, everything is an object. An object is a collection of related functionality stored in a single grouping. You can create your own objects, but that is quite advanced. The built-in objects that your browser contains allow you to do lots of useful things.

For example, we first created a guessField variable that stores a reference to the text input form field in our HTML(To get this reference, we used the querySelector() method of the document object).

Because guessField now contains a reference to an <input> element, it will now have access to a number of properties (basically variables stored inside objects, some of which can't have their values changed) and methods (basically functions stored inside objects).

页面上的每一个元素都有一个style属性,它自己包含一个对象,其属性包含应用于该元素的全部内联CSS样式。 这容许咱们使用JavaScript在元素上动态设置新的CSS样式。

什么地方出了错?

浏览器的控制台能够检查JavaScript是否有语法错误并提示错误信息。有的错误要和网页交互后控制台才能提示,好比错误在函数内部发生,相对于函数外部的代码,函数内部的代码运行在一个独立的范围中,在这种状况下,页面加载时函数内部的代码不会被运行也不会抛出异常。

console.log() is a really useful debugging function that prints a value to the console. log是日志的意思。

如何存储你须要的信息变量

变量是用来存储数值的,那么有一个重要的概念须要区分。变量不是数值自己,它们仅仅是一个用于存储数值的容器。你能够把变量想象成一个个用来装东西的纸箱子。

在JavaScript中,全部代码指令都会以分号结尾 (;) — 若是忘记加分号,虽然浏览器的JS引擎会帮你加上,但不必定可靠,因此最好是养成主动以分号做为代码结尾的习惯。

变量名不要如下划线开头—— 如下划线开头的被某些JavaScript设计为特殊的含义,所以可能让人迷惑。

一个可靠的命名约定叫作 "小写驼峰命名法",用来将多个单词组在一块儿,小写整个命名的第一个字母而后大写剩下单词的首字符。

与其余编程语言不一样,在 JavaScript 中你不须要声明一个变量的类型,由于JavaScript是一种“松散类型语言”。

字符串是文本的一部分。当你给一个变量赋值为字符串时,你须要用单引号或者双引号把值给包起来,二者之间几乎没有什么区别,根据我的偏好来使用。可是,您应该选择一个并坚持使用它。

数组是一个单个对象,其中包含不少值,方括号括起来,并用逗号分隔。

In programming, an object is a structure of code that models a real life object. You can have a simple object that represents a car park and contains information about its width and length, or you could have an object that represents a person, and contains data about their name, height, weight, what language they speak, how to say hello to them, and more.

可用对象字面量建立对象,好比var dog = { name : 'Spot', breed : 'Dalmatian' };。

JavaScript中的基础数学数字和操做符

Unlike some other programming languages, JavaScript only has one data type for numbers, you guessed it, Number. 这意味着,你在JavaScript中处理的任何类型的数字,都以彻底相同的方式处理它们。因此整数除以整数的结果能够是浮点数。

A control that swaps between two states is generally referred to as a toggle. It toggles between one state and another — light on, light off, etc.

运算符typeof:参数能够是变量,返回数据类型。注意,是运算符。格式,typeof myInt;。吐槽:我无语了,这个运算符的字母o是小写的,可是方法indexOf()的字母O倒是大写的。

文本处理 JavaScript中的字符串

想在字符串中包含单引号(双引号),那包裹字符串的就应该用双引号(单引号),或者用转义字符——反斜杠\。

字符串和数字也能用加号相连(浏览器会自动把数字转换为字符串)。

函数Number()能把字符串转换为数字。

方法toString()能把数字转换为字符串。

有用的字符串方法

咱们曾经说过,如今咱们重申一遍—在javascript中,一切东西均可以被当作对象。

When you create a string, your variable becomes a string object instance, and as a result has a large number of properties(即.XXX and methods(即.XXX() available to it.

您可使用方括号符号返回字符串中的字符。

属性length:获取字符串或数组的长度。

注意:数组也有indexOf()和slice()方法。

方法indexOf():在字符串中查找子字符串,参数是要查找的子字符串,返回子字符串的第一个字符的下标。找不到则返回-1。吐槽:我无语了,这个方法的字母O是大写的,可是运算符typeof的字母o倒是小写的。

方法slice():提取子字符串,参数是字符的下标,返回子字符串。slice()的第二个参数是可选的(表示要提取的子字符串的最后一个字符的下一个下标),若是你没有传入第二个参数,这个分片的结束位置会在原始字符串的末尾。

方法toLowerCase()和toUpperCase():大小写转换(全部字符),不须要参数,返回转换后的字符串。

方法replace():将字符串中的一个子字符串替换为另外一个子字符串,须要两个参数 - 要被替换下的子字符串和要被替换上的子字符串,返回替换后的字符串。注意,想要真正更新变量的值,您须要设置变量的值等于返回的结果,它不会自动更新变量的值。——这样只能替换匹配到的第一个子字符串,要想替换全部子字符串,惟一的办法就是提供一个正则表达式。

函数和方法直观的区别是,方法前面有“XXX.”;内在的区别是函数是通用的,而方法是属于某一个对象的函数。

数组

Bear in mind that you can store any item in an array — string, number, object, another variable, even another array. You can also mix and match item types — they don't all have to be numbers, strings, etc, just like this: var random = ['tree', 795, [0, 1, 2]];.

字符串的方法split():在其最简单的形式中,须要一个参数——您要将字符串分隔的字符——并返回分隔符之间的子串,做为数组中的项。这在技术上是一个字符串的方法,而不是一个数组的方法,可是咱们把它放在数组这里来说,是由于它在这里很好。

方法join():这个是数组的方法,进行与split()相反的操做,能够指定一个参数(不指定则默认是逗号)做为分隔符。而若是用方法toString(),则不能指定参数,只能是逗号做为分隔符。

方法push()和方法pop():在数组末尾添加或删除项目。push()的参数能够有多个,即一次添加多个数组项,返回数组的新长度;pop()不须要参数,返回已删除的项目。unshift()和shift()(shift意思是“去掉”)以彻底相同的方式工做,只是它们在数组的开始处,而不是结尾。

函数Math.round():四舍五入填入括号内的参数。

 

JavaScript 基础要件

在代码中作决定 - 条件语句

有时候你可能会看到 if…else 语句没有写花括号(但要写在同一行),这是彻底有效的代码,但不建议这样使用——由于若是有花括号进行代码切割的话,总体代码被切割为多行代码,更易读和易用。即便只有一句代码,也最好加上花括号。

Any value that is not false, undefined, null, 0, NaN, or an empty string ('') actually returns true when tested as a conditional statement. 所以您甚至可使用变量是否是未定义的(即有没有被赋值)来做为条件。

&& — 逻辑与

|| — 逻辑或

! — 逻辑非

Note: switch语句的default 部分(不须要break语句)不是必须的 - 若是表达式不可能存在未知值,则能够安全地省略它。 若是有机会,您须要包括它来处理未知的状况。

JS也有三元运算符,即XXX?XXX:XXX。

若是写成if (x === 5 || 7),则极可能写错了,本意应该是if (x === 5 || x === 7)。

循环语句

若是要在全部迭代完成以前退出循环,可使用break语句。

JS也有C++有的continue语句。

除了for语句,也有while语句和do ... while语句(后二者能作的,for语句通常也能作)。咱们建议使用for,由于它可能能最简单地帮你记住一切 - 初始化程序,退出条件和最终表达式都必须整齐地放入括号,因此很容易看到他们在哪里并检查你没有丢失他们。

无限循环的结果是要么浏览器强制终止它,要么它本身崩溃。

函数-可复用的代码块

JavaScript的函数的定义位置随便在哪,在使用前或使用后都行(前提是在一个js文件中并且不能是用函数表达式定义,即要用函数声明)。

In fact, some of the code you are calling when you invoke (a fancy word for run, or execute) a built in browser function couldn't be written in JavaScript — many of these functions are calling parts of the background browser code, which is written largely in low-level system languages like C++, not web languages like JavaScript. Bear in mind that some built-in browser functions are not part of the core JavaScript language — some are defined as part of browser APIs, which build on top of the default language to provide even more functionality.

Technically speaking, built-in browser functions are not functions — they are methods. The distinction is that methods are functions defined inside objects. Built-in browser functions (methods) and variables (which are called properties) are stored inside structured objects, to make the code more efficient and easier to handle.

匿名函数:You generally use an anonymous function along with an event handler. 你还能够将匿名函数分配为变量的值,但这只会使人费解,因此不要这样作!

主要使用匿名函数来运行负载的代码以响应事件触发(如点击按钮)。

Note:当您须要指定多个参数时,它们以逗号分隔(指JS。而CSS有点奇葩)。

若是重复定义一个变量或函数,结果固然是后定义的。

注意:函数做用域的规则不适用于循环(for(){...})和条件块(if(){...} - 它们看起来很是类似,但它们不同!也就是说,forif外的代码也能够用forif里面的东西。

注意:ReferenceError: "x" is not defined错误是您遇到的最多见的错误。若是您收到此错误,而且肯定您已经定义了该问题的变量,就请检查它的做用域范围。

建立您本身的函数

document.querySelector()(参数是CSS中的选择器):a DOM API function,用来选择元素。而后能够把它存放在一个变量中, 这样方便咱们接下来使用这个元素。例子:var html = document.querySelector('html');,变量名能够和元素名相同。注:document均可换成element,。

document.createElement()(参数是元素名):a DOM API function,用来建立元素。而后能够把该新建元素的引用(其实是新建对象的地址)放在一个变量中。例子:var panel = document.createElement('div');。

Element.setAttribute()(Element指引用了HTML中的元素的JS变量;第一参数是属性,第二个参数是值):a DOM API function,给元素添加属性和值,若是属性已经存在,则更新值。它能够方便咱们给元素添加样式。例子:panel.setAttribute('class', 'msgBox');。

Node.textContent:a property(属性),  represents the text content of an element — 能够用来改变元素的文本内容。例子:var msg = document.createElement('p');msg.textContent = 'This is a message box';。和innerHTML的效果差很少。二者都为彻底替换元素内容提供了一个更加便捷的方式。举个例子,能够经过以下代码彻底删除文档内body的内容:document.body.innerHTML = "";或document.body. textContent = "";

Node.appendChild()(Node指引用了HTML中的元素的JS变量):a DOM function,给变量(咱们以前定义好的)追加元素 。该方法追加了元素的同时也把元素指定为Node的子元素 。这样作是由于咱们建立了一个元素以后这个元素并不会莫名其妙地出如今咱们的页面上(浏览器只知道咱们建立了一个元素,可是不知道把这个元素怎么呈现出来) — 所以,咱们给这个元素一个定位,就是显示在Node引用的HTML中的元素里面!例子:html.appendChild(panel);,这里的html是在JS里定义的变量。

onclick:a property that can be set to a function to specify what code to run when the button is clicked. 能够给 onclick 事件处理器绑定一个匿名函数, 函数中的代码就会在元素被点击的时候运行。onclick就像其它属性同样(好比textContent),只不过有一个特别的地方——当您将一些代码赋给它的时候,只要事触发,代码就会运行。

Node.removeChild():a DOM API function, 指定咱们想要移除的HTML中的子元素。至少,你要拥有要删除的节点和其父节点的引用。例子(panel.parentNode即panel的父节点):panel.parentNode.removeChild(panel);。另外,The ChildNode.remove() method removes the object from the tree it belongs to.

不必定要在函数声明后面才调用函数,在C语言中确实是要先定义后使用,可是咱们如今用的是JavaScript,它很强大,无论你是先定义后调用仍是先调用后定义都行,可是别忘了定义。

btn.onclick = displayMessage;:You might be wondering why we haven't included the parentheses(括号) after the function name. This is because we don't want to call the function immediately — only after the button has been clicked. 若是加了括号,you'll see that the message box appears without the button being clicked! The parentheses in this context are sometimes called the "function invocation(调用) operator". You only use them when you want to run the function immediately in the current scope. In the same respect, the code inside the anonymous function(匿名函数) is not run immediately, as it is inside the function scope.

一个定义了两个参数的函数,能够只使用一个参数进行调用。

Node.style.backgroundImage、Node.style.backgroundColor、Node.style.paddingLeft(这些属性的值都有加引号)

函数返回值

Node.value

onchange: runs whenever the change event fires.

isNaN():判断参数的值是否是数字。若是不是,就返回true。

事件介绍

Events are actions or occurrences that happen in the system you are programming, which the system tells you about so you can respond to them in some way if desired.

Each available event has an event handler(事件处理器), which is a block of code (usually a user-defined JavaScript function) that will be run when the event fires. When such a block of code is defined to be run in response to an event firing, we say we are registering an event handler. Note that event handlers are sometimes called event listeners(事件监听器)——从咱们的用意来看这两个名字是相同的,尽管严格地说来这块代码既监听也处理事件。监听器留意事件是否发生,而后处理器就是对事件发生作出的回应。

注: web events不是核心 JavaScript 语言的一部分——它们是做为浏览器内置的JavaScript APIs的一部分被定义的。

document.body.style.backgroundColor

理解JavaScript在不一样环境下使用不一样的事件模型很重要——从Web api到其余领域,如浏览器WebExtensions(用于开发跨浏览器的插件)和Node.js(服务器端JavaScript)。

The event model in JavaScript for web pages differs from the event model for JavaScript as it is used in other environments. For example, Node.js is a very popular JavaScript runtime that enables developers to use JavaScript to build network and server-side applications. The Node.js event model relies on listeners to listen for events and emitters(发射器) to emit events periodically ——虽然听起来好像差很少,可是实现二者的代码是很是不一样的,Node.js 使用 on ( ) 这样的函数来注册一个事件监听器,使用 once ( ) 这样函数来注册一个在运行一次以后注销的监听器。

也能够将一个有名字的函数的名字赋值给事件处理器。

有许多不一样的事件处理器属性(properties)可选:

btn.onfocus和btn.onblur — 代码将于按钮被置于焦点或解除焦点时执行。btn可换成别的。

btn.ondblclick — 代码将仅于按钮被双击时执行(不要使用dblclick执行重要的操做,由于键盘没法触发这个事件)。btn可换成别的。

window.onkeypress, window.onkeydown, window.onkeyup — 代码将于按一下键、按下键或松开键时执行(能够把window换成别的)。

btn.onmouseover 和 btn.onmouseout — 代码将会在鼠标移入按钮上方时执行, 或者当它从按钮移出时。btn可换成别的。

不要使用内联的事件处理器。

将您的编程逻辑与内容分离也会使您的站点对搜索引擎更加友好。

addEventListener()和removeEventListener():addEventListener()这个函数和事件处理器属性(properties)是相似的,可是语法略有不一样。例子:btn.onclick = bgChange;和btn.addEventListener('click', bgChange);是等效的。若是须要,可使用removeEventListener()删除事件处理器代码,并且若是须要,您能够向同一类型的元素添加多个监听器。例如,您能够在一个元素上屡次调用addEventListener('click', function() { ... }),而第二个参数中指定不一样的函数。对于事件处理器属性来讲,这是不可能的,由于后面设置的属性会覆盖较早的属性。

只要可能,应该用DOM Level 2 Events (addEventListener(), etc.)。

事件对象(event objects, 即参数e):It is automatically passed to event handlers to provide extra features and information.

事件对象 e target属性始终是刚刚发生的事件所在的元素的引用。您可使用任何您喜欢的名称做为事件对象。开发人员最常使用 e / evt / event,由于它们很简单易记。坚持标准老是很好。当您要在多个元素上设置相同的事件处理程序时,e.target很是有用(this不也同样吗,要写的代码还更少事件委托的状况下不同,只能用e.target——不过注意,即便是其他状况,this也只能代替e.target,e的别的功能代替不了)。例如,你可能有一组16块方格,当它们被点击时就会消失。用e.target老是能准确选择当前操做的东西(方格)并执行操做让它消失,而不是必须以更困难的方式选择它。

一些浏览器支持自动的表单数据验证功能,但因为许多浏览器不支持,所以建议你不要依赖这些功能,并实现本身的验证检查。

onsubmit

document.getElementById()

e.preventDefault():阻止默认行为,好比表单的提交。

如何控制一个元素的显示和隐藏?想隐藏能够把元素放到屏幕外或者用display: none或者用visibility: none。

当一个事件发生在具备父元素的元素上时,现代浏览器运行两个不一样的阶段 - 捕获阶段和冒泡阶段。

在捕获阶段:

  • 浏览器检查元素的最外层祖先<html>,是否在捕获阶段中注册了一个onclick事件处理程序,若是是,则运行它。
  • 而后,它移动到<html>中的下一个元素,并执行相同的操做,而后是下一个元素,依此类推,直到到达实际点击的元素。

在冒泡阶段,偏偏相反:

  • 浏览器检查实际点击的元素是否在冒泡阶段中注册了一个onclick事件处理程序,若是是,则运行它
  • 而后它移动到下一个直接的祖先元素,并作一样的事情,而后是下一个,等等,直到它到达<html>元素。

在现代浏览器中,默认状况下,全部事件处理程序都在冒泡阶段进行注册。这在大多数状况下更有意义。若是您真的想在捕获阶段注册一个事件,那么您能够经过使用addEventListener()注册您的处理程序,并将可选的第三个属性设置为true。

标准事件对象具备可用的名为 stopPropagation()(Propagation意为传播)的函数, 当在事件对象上调用该函数时,它只会让当前事件处理程序运行,但事件不会在冒泡链上进一步扩大,所以将不会有更多事件处理器被运行(不会向上冒泡)。

事件委托(Event delegation):冒泡还容许咱们实现事件委托——这个概念依赖于这样一个事实,若是你想要在大量子元素中单击任何一个均可以运行一段代码,您能够将事件监听器设置在其父节点上,并将事件监听器气泡的影响设置为每一个子节点,而不是每一个子节点单独设置事件监听器。

一个很好的例子是一系列列表项,若是你想让每一个列表点击时弹出一条信息,您能够将click单击事件监听器设置在父元素<ul>上,它将会冒泡到列表项上。

getAttribute():参数为某个Attribute,返回该Attribute的value。

 

JavaScript 对象介绍

在 JavaScript 中,大多数事物都是对象, 从做为核心功能的字符串和数组,到创建在 JavaScript 之上的浏览器 API。

对象基础

An object is a collection of related data and/or functionality (which usually consists of several variables and functions — which are called properties and methods when they are inside objects.)

一个对于初学者很常见的错误是在最后一个成员后面多了一个逗号,这会引起错误。

一个对象由许多的成员组成,每个成员都拥有一个名字(如name、age),和一个值(如['Bob', 'Smith']、32)。每个名字/值(name/value)对被逗号分隔开,而且名字和值之间由冒号(:)分隔。成员的值能够是函数(function)。值不是函数的成员叫属性(property),值是函数的成员叫方法(method)。

object literal(对象的字面量) — we've literally written out the object contents as we've come to create it.

当你想要传输一些有结构和关联的资料时常见的方式是使用字面量来建立一个对象,举例来讲,发起一个请求到服务器以存储一些数据到数据库,发送一个对象要比分别发送这些数据更有效率,并且比起数组更为易用,由于你使用名字(name)来标识这些资料。

The object name (如person) acts as the namespace.

除了用dot notation来访问对象的属性和方法,还能用bracket notation。好比,person['name']['first']和person.name.first是等价的。这看起来很像访问一个数组的元素,从根本上来讲是一回事儿,你使用了关联了值的名字,而不是索引去选择元素。难怪对象有时被称之为关联数组(associative array)了——对象作了字符串到值的映射,而数组作的是数字到值的映射。你用dot notation和bracket notation不只更新已经存在的成员的值,还可建立新的成员。bracket notation一个有用的地方是它不只能够动态地设置成员的值,还能够动态地设置成员的名字,以下:

var myDataName = 'height';

var myDataValue = '1.75m';

person[myDataName] = myDataValue;

Adding a property to an object using the method above isn't possible with dot notation, which can only accept a literal member name, not a variable value pointing to a name.

For each webpage loaded, an instance of Document is created, called document, which represents the entire page's structure, content, and other features such as its URL.

built-in API 等于 built-in object

It is useful to think about the way objects communicate as message passing — when an object needs another object to perform some kind of action often it will send a message to another object via one of its methods, and wait for a response, which we know as a return value.

你应该清楚对象有利于存储一些相关联的数据和函数,若是你尝试以分开的方式去保存person对象包含的全部的属性和方法,这是使人沮丧且效率低下的,并且会有不少的变量和函数之间同名的风险。对象使咱们将一些信息安全地锁在了它们本身的包内,防止它们被损坏。

适合初学者的JavaScript面向对象

注:本节内容很是难懂,作好心理准备(可能还不如看https://www.cnblogs.com/shuiyi/p/5305435.html

基本的 OOP 思想就是使用对象来模仿咱们想要在咱们的程序中表现的现实世界的事物, 同时提供一种简单的方式来访问这些事物的功能。(The basic idea of OOP is that we use objects to model real world things that we want to represent inside our programs, and/or provide a simple way to access functionality that would otherwise be hard or impossible to make use of.)

Object data (and often, functions too) can be stored neatly (the official word is encapsulated(封装)) inside an object package (which can be given a specific name to refer to, which is sometimes called a namespace), making it easy to structure and access; objects are also commonly used as data stores that can be easily sent across the network.

abstraction(抽象) — creating a simple model of a more complex thing, which represents its most important aspects in a way that is easy to work with for our program's purposes.

在一些面向对象的语言中,咱们用类(class)的概念去描述一个对象(您在下面就能看到JavaScript使用了一个彻底不一样的术语)-类并不彻底是一个对象,它更像是一个定义对象特质的模板。注:红宝书说JS没有类。

When an object instance is created from a class, the class's constructor function(构造函数,used to define objects and their features. is run to create it. This process of creating an object instance from a class is called instantiation(实例化) — the object instance is instantiated from the class.

The fancy word for the ability of multiple object types to implement the same functionality is polymorphism(多态).

The constructor function below is JavaScript's version of a class, 它只定义了对象的属性和方法,没有明确建立一个对象和返回任何值(构造函数模式):

function Person(name) {

  this.name = name;

  this.greeting = function() {

    alert('Hi! I\'m ' + this.name + '.');

  };

}    

若是不用this,就要写成这样(工厂模式。注意,这不是构造函数):

function createNewPerson(name) {

  var obj = {};

  obj.name = name;

  obj.greeting = function () {

    alert('Hi! I\'m ' + this.name + '.');

  }

  return obj;

}

因此,this能简化构造函数的编写。

Note: A constructor function name usually starts with a 大写字母 — this convention(惯例) is used to make constructor functions easier to recognize in code.

那如何调用构造函数建立新的实例呢?答:var person1 = new Person('Bob'); 。the new keyword is used to tell the browser we want to create a new object instance.

When we are calling our constructor function, we are defining greeting() every time(由于方法直接定义在了构造器函数里而不是prototype属性里), which isn't ideal. To avoid this, we can define functions on the prototype(原型) instead, which we will look at later.

同一个构造函数建立出的不一样实例被存储在不一样的命名空间里。

Sub-namespaces: It is possible to make the value of an object member another object(即对象中的对象).

So far we've seen two different ways to create an object instance— declaring an object literal, and using a constructor function(上面还提到第三种,工厂模式). These make sense, but there are other ways — we want to make you familiar with these in case you come across them in your travels around the Web.

The Object() constructor: You can use the Object() constructor to create a new object. Yes, even generic objects have a constructor, which generates an empty object. 例子:var person1 = new Object();

Using the create() method: Some people prefer to create object instances without first creating constructors, especially if they are creating only a few instances of an object. JavaScript has a built-in method called create() that allows you to do that. With it, you can create a new object based on any existing object. 例子: var person2 = Object.create(person1);

Object prototypes

Prototypes are the mechanism(机制) by which JavaScript objects inherit features from one another. The prototype property can be used to add methods to existing constructors.

JavaScript is often described as a prototype-based language — each object has a prototype object, which acts as a template object that it inherits methods and properties from. An object's prototype object may also have a prototype object, which it inherits methods and properties from, and so on. This is often referred to as a prototype chain(原型链).

To be exact, the properties and methods are defined on the prototype property on the Objects' constructor functions, not the object instances themselves.

It's important to understand that there is a distinction between an object's prototype and the prototype property on constructor functions. The former is the property on each instance, and the latter is the property on the constructor. That is, Object.getPrototypeOf(new Foobar()) refers to the same object as Foobar.prototype.

举个栗子:person1's prototype object is the Person() (Person() is the constructor). person1中除了有在原型对象Person()中定义的成员外,还有一些其它成员,they are defined on the Person() 's prototype object, which is Object. 就像下图所示:

 

 

What happens if you call a method on person1, which is actually defined on Object? For example:

person1.valueOf()

This method simply returns the value of the object it is called on — try it and see! In this case, what happens is(当js引擎查找对象的属性或方法时,先在对象自己上找(但不会在对象的prototype属性中找),找不到就顺着原型链、在原型链上的对象的prototype属性中找):

  • The browser initially checks to see if the person1 object has a valueOf() method available on it.
  • It doesn't, so the browser then checks to see if the person1 object's prototype object (Person() constructor's prototype) has a valueOf() method available on it.
  • It doesn't either, so the browser then checks to see if the Person() constructor's prototype object's prototype object (Object() constructor's prototype) has a valueOf() method available on it. It does, so it is called, and all is good!

Note: 必须重申,原型链中的方法和属性没有被复制到其余对象 — they are accessed by walking up the chain as described above.

The inherited ones are the ones defined on the prototype property (you could call it a sub-namespace) — that is, the ones that begin with Object.prototype., and not the ones that begin with just Object.

Person.prototype和Object.prototype之类的是指Person、Object的prototype属性,要指Person、Object的原型对象,则要用.__proto__

重要:prototype 属性大概是 JavaScript 中最容易混淆的名称之一。你可能会认为,这个属性指向当前对象的原型对象,其实不是(还记得么?原型对象是一个内部对象,应当使用 __proto__ 访问)。prototype 属性包含(指向)一个对象,你在这个对象中定义须要被继承的成员。

var person2 = Object.create(person1);

create() 实际作的是从指定原型对象建立一个新的对象。这里以 person1 为原型对象建立了 person2 对象。在控制台输入:person2.__proto__结果返回 person1 对象。

每一个对象实例都具备 constructor 属性,它指向建立该实例的构造器函数。

person1.constructor和person2.constructor都将返回 Person() 构造器,由于该构造器包含这些实例的原始定义。一个小技巧是,你能够在 constructor 属性的末尾添加一对圆括号(括号中包含所需的参数),从而用这个构造器建立另外一个对象实例。毕竟构造器是一个函数,故能够经过圆括号调用;只需在前面添加 new 关键字,便能将此函数做为构造器使用。一般你不会去用这种方法建立新的实例;但若是你恰好由于某些缘由没有原始构造器的引用,那么这种方法就颇有用了。此外,constructor 属性还有其余用途。好比,想要得到某个对象实例的构造器的名字,能够这么用:instanceName.constructor.name。具体地,像这样:person1.constructor.name。

为构造器的 prototype 属性添加一个新的方法,则整条继承链动态地更新了,任何由此构造器建立的对象实例都自动得到了这个方法。旧有对象实例的可用功能被自动更新了。这证实了先前描述的原型链模型。这种继承模型下,上游对象的方法不会复制到下游的对象实例中;下游对象自己虽然没有定义这些方法,但浏览器会经过上溯原型链、从上游对象中找到它们。这种继承模型提供了一个强大而可扩展的功能系统。

你不多看到属性定义在 prototype 属性中,由于如此定义不够灵活。Person.prototype.fullName = this.name.first + ' ' + this.name.last;这么作的话,this 引用的是全局范围,而非函数范围。访问这个属性只会获得 undefined undefined(除非全局真有name这个对象和相应的属性)。但这个语句若放在prototype属性的方法中则不会发生这种状况,由于此时语句位于函数范围内,从而可以成功地转换为对象实例范围。你可能会在 prototype属性上定义常属性 (constant property) (指那些你永远无需改变的属性),但通常来讲,在构造器内定义属性更好。

一种极其常见的对象定义模式是,在构造函数(constructor)中定义属性(properties)、在 prototype 属性上定义方法(methods)。如此,构造函数只包含属性定义,而方法则分装在不一样的代码块,代码更具可读性。例如:

// 构造函数及其属性定义

function Test(a,b,c,d) {

  // 属性定义

};

// 定义第一个方法

Test.prototype.x = function () { ... }

// 定义第二个方法

Test.prototype.y = function () { ... }

// 等等……

JavaScript 中的继承

栗子:

function Teacher(first, last, age, gender, interests, subject) {

  Person.call(this, first, last, age, gender, interests);

 

  this.subject = subject;

}

Teacher.prototype = Object.create(Person.prototype) //或者 new Person();

Teacher.prototype.constructor = Teacher;

每个函数对象(Function)都有一个prototype属性,而且只有函数对象有prototype属性,由于prototype自己就是定义在Function对象下的属性。当咱们输入相似var person1=new Person(...)来构造对象时,JavaScript实际上参考的是Person.prototype指向的对象来生成person1。另外一方面,Person()函数是Person.prototype的构造函数,也就是说Person===Person.prototype.constructor(不信的话能够试试)。

在定义新的构造函数Teacher时,咱们经过function.call来调用父类的构造函数。而后咱们利用Object.create()方法将Person.prototype做为Teacher.prototype的原型对象,并改变其构造器指向,使之与Teacher关联。

任何您想要被继承的方法都应该定义在构造函数的prototype对象里,而且永远使用父类的prototype来创造子类的prototype,这样才不会打乱类继承结构。

就在本身代码中使用继承而言,您可能不会使用得很是频繁,特别是在小型项目中或者刚开始学习时 - 由于当您不须要对象和继承的时候,仅仅为了使用而使用它们只是在浪费时间而已。可是随着您的代码量的增大,您会愈来愈发现它的必要性。若是您开始建立一系列拥有类似特性的对象时,那么建立一个包含全部共有功能的通用对象,而后在更特殊的对象类型中继承这些特性,将会变得更加方便有用。

Because of the way JavaScript works, with the prototype chain, etc., the sharing of functionality between objects is often called delegation.

在使用继承时,建议您不要使用过多层次的继承,并仔细追踪定义方法和属性的位置。颇有可能您的代码会临时修改了浏览器内置对象的原型,但您不该该这么作,除非您有足够充分的理由。过多的继承会在调试代码时给您带来无尽的混乱和痛苦。

 

Ultimately(根本上), objects are just another form of code reuse(重用), like functions or loops, with their own specific roles and advantages. If you find yourself creating a bunch of related variables and functions and want to track them all together and package them neatly, an object is a good idea. Objects are also very useful when you want to pass a collection of data from one place to another. Both of these things can be achieved without use of constructors or inheritance. If you only need a single instance of an object, then you are probably better off just using an object literal, and you certainly don't need inheritance.(总之,对象是另外一种形式的代码重用,就像函数和循环同样,有他们特定的角色和优势。若是您发现本身建立了一堆相关的变量和函数,还想一块儿追踪它们并将其灵活打包的话,对象是个不错的主意。对象在您打算把一个数据集合从一个地方传递到另外一个地方的时候很是有用。这两种状况均可以在不使用构造器和继承的状况下完成。若是您只是须要一个单一的对象实例,也许使用对象常量会好些,您固然不须要使用继承。)

Working with JSON

JavaScript Object Notation (JSON) is a standard text-based format for representing structured data based on JavaScript object syntax(JSON是一种基于文本的格式,表明结构化的数据,基于JS对象语法).

JSON exists as a string — useful when you want to transmit data across a network. It needs to be converted to a native JavaScript object when you want to access the data. This is not a big issue —  JavaScript provides a global JSON object that has methods available for converting between the two.

Note: Converting a string to a native object is called parsing(解析), while converting a native object to a string so it can be transmitted across the network is called stringificationstring化).

A JSON object can be stored in its own file, which is basically just a text file with an extension of .json, and a MIME type of application/json.

A JSON is a string whose format very much resembles JavaScript object literal format. You can include the same data types inside JSON as you can in a standard JavaScript object — strings, numbers, arrays, booleans, and other object literals.

咱们使用 . 或 [] 访问对象内的数据。

”咱们已经能够推测出 JSON 对象就是基于JavaScript 对象,并且这几乎是正确的“——咱们说几乎正确的缘由是数组也是一种合法的 JSON 对象(其实数组也是JavaScript 对象)。

JSON 是一种纯数据格式,它只包含属性,没有方法。

JSON 要求有两头的 { } 来使其合法。

甚至一个错位的逗号或分号就能够致使  JSON 文件出错。您应该当心的检查您想使用的数据(虽然计算机生成的 JSON 不多出错,只要生成程序正常工做)。您能够经过像 JSONLint 的应用程序来检验 JSON。

为了载入 JSON 到页面中,咱们将使用 一个名为XMLHTTPRequest的API(常称为XHR)。这是一个很是有用的 JavaScript 对象,使咱们可以经过代码来向服务器请求资源文件(如:图片,文本,JSON,甚至HTML片断),意味着咱们能够更新小段内容而不用从新加载整个页面。

举个栗子:

var requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';

var request = new XMLHttpRequest();:为了建立一个HTTP请求,咱们须要建立一个HTTP请求对象。

request.open('GET', requestURL);:使用 open() 函数打开一个新的请求。这个函数至少含有两个参数,其它的是可选参数。

request.responseType = 'json'; request.send();:设定 responseType 为 JSON,因此服务器将知道咱们想要返回一个 JSON 对象,而后发送请求。这样作的话,就访问 JSON 而言是简单的,由于咱们设置了 XHR 来访问 JSON 格式数据

request.onload = function() {

  var superHeroes = request.response;

  populateHeader(superHeroes);

  showHeroes(superHeroes);

}:这儿咱们保存了相应咱们请求的数据(访问 response 属性) 于变量 superHeroes ;这个变量如今含有 JSON!咱们如今把superHeroes传给两个函数,第一个函数将会用正确的数据填充<header>,同时第二个函数将建立一个信息卡片,而后把它插入<section>中。咱们把代码包在事件处理函数中,当请求对象load事件触发时执行代码,这是由于请求对象load事件只有在接收到完整的响应数据时触发;这种方式能够保证事件触发时request.response 是绝对能够访问的。注:populateHeader()和showHeroes()是自定义的函数。

有时候,咱们接收到一些 字符串做为 JSON 数据,而后咱们想要将它转换为对象。当咱们想要发送 JSON 数据做为信息,咱们将须要转换它为字符串,咱们常常须要正确的转换数据,幸运的是,这两个问题在web环境中是那么广泛以致于浏览器拥有一个内建的 JSON,包含如下两个方法

parse(): 以文本字符串形式接受JSON对象做为参数,并返回相应的对象。。

stringify(): 接收一个对象做为参数,返回一个对应的JSON字符串。

实践对象构造

打开浏览器中的 JavaScript 控制台后,刷新页面,可更新F12中的盒模型数据(前提是盒模型的尺寸确实变了)。

 

客户端网页 API

Web API简介

  • JavaScript — A high-level scripting language built into browsers that allows you to implement functionality on web pages/apps. Note that JavaScript is also available in other programming environments, such as Node.
  • Browser APIs — constructs built into the browser that sit on top of the JavaScript language and allow you to implement functionality more easily(好比DOM、BOM).
  • Third party APIs — constructs built into third-party platforms (e.g. Twitter, Facebook) that allow you to use some of those platform's functionality in your own web pages (for example, display your latest Tweets on your web page).
  • JavaScript libraries — Usually one or more JavaScript files containing custom functions that you can attach to your web page to speed up or enable writing common functionality. Examples include jQuery, Mootools and React.
  • JavaScript frameworks — The next step up from libraries, JavaScript frameworks (e.g. Angular and Ember) tend to be packages of HTML, CSS, JavaScript, and other technologies that you install and then use to write an entire web application from scratch. The key difference between a library and a framework is “Inversion(倒置) of Control”. When calling a method from a library, the developer is in control. With a framework, the control is inverted: the framework calls the developer's code.

匿名函数的括号们的放置能够像这样:

navigator.geolocation.getCurrentPosition(function(position) {

  ……

});

仅在操做完成时调用函数的模式在JavaScript API中很是常见 - 确保一个操做已经完成,而后在另外一个操做中尝试使用该操做返回的数据。这些被称为 asynchronous  “异步”操做。因为获取设备的当前位置依赖于外部组件(设备的GPS或其余地理定位硬件), we can't guarantee that it will be done in time to just immediately use the data it returns. 所以,这样子是行不通的:

var position = navigator.geolocation.getCurrentPosition();

var myLatitude = position.coords.latitude;

若是第一行尚未返回结果(第一行是异步的),则第二行将会出现错误,由于位置数据还不可用。 出于这个缘由,涉及异步操做的API被设计为使用 callback functions “回调函数”,或更现代的 Promises 系统,这些系统在ECMAScript 6中可用,并被普遍用于较新的API。

API使用一个或多个 JavaScript objects 在您的代码中进行交互,这些对象用做API使用的数据(包含在对象属性中)的容器以及API提供的功能(包含在对象方法中)。

您将在许多API中看到两种常见模式:首先,API对象一般包含构造函数,能够调用这些构造函数来建立用于编写程序的对象的实例。 其次,API对象一般有几个可用的options,能够调整以得到您的程序所需的确切环境(根据不一样的环境,编写不一样的Options对象)。 API构造函数一般接受options对象做为参数,这是您设置这些options的地方。

使用API时,应确保知道API入口点的位置。 在Geolocation API中,这很是简单 - 它是 Navigator.geolocation 属性, 它返回浏览器的 Geolocation 对象,全部有用的地理定位方法均可用。文档对象模型 (DOM) API有一个更简单的入口点 —它的功能每每被发现挂在 Document 对象, 或任何你想影响的HTML元素的实例。

一些Web API不包含事件,但有些包含一些事件。

WebAPI功能受到与JavaScript和其余Web技术(例如同源政策)相同的安全考虑,可是他们有时会有额外的安全机制。

Manipulating(操纵) documents

直接出如今web页面视图中的浏览器的主要部分:

  • window是载入浏览器的标签,使用这个对象的可用方法,你能够返回窗口的大小(参见window.innerWidthwindow.innerHeight),操做载入窗口的文档,存储客户端上文档的特殊数据(例如使用本地数据库或其余存储设备),为当前窗口绑定event handler,等等。
  • navigator表示浏览器(即用户代理)的状态和身份。你能够用这个对象获取一些信息,好比来自用户摄像头的地理信息、用户偏心的语言、多媒体流等等。
  • document(在浏览器中用DOM表示)是载入窗口的实际页面,你能够用这个对象来返回和操做文档中HTML和CSS上的信息。例如获取DOM中一个元素的引用,修改其文本内容,并应用新的样式,建立新的元素并添加为当前元素的子元素,甚至把他们一块儿删除。

在浏览器标签中当前载入的文档用文档对象模型来表示。这是一个由浏览器生成的“树结构”,使编程语言能够很容易地访问HTML结构 — 例如浏览器本身在呈现页面时,使用它将样式和其余信息应用于正确的元素,而页面呈现完成之后,开发人员能够用JavaScript操做DOM。文档中每一个元素和文本在树中都有它们本身的入口 — 称之为节点(node)(即节点包括元素和文本)

要操做DOM内的元素,首先须要选择它,并将它的引用存储在一个变量中,栗子:var link = document.querySelector('a');——Now we have the element reference stored in a variable, we can start to manipulate it using properties and methods available to it (these are defined on interfaces like HTMLAnchorElement in the case of <a> element, its more general parent interface HTMLElement, and Node — which represents all nodes in a DOM).

注意,有不少方法能够选择一个元素,并在一个变量中存储一个引用。Document.querySelector()是推荐的主流方法,它容许你使用CSS选择器选择元素,使用很方便。上面的querySelector()调用会匹配它在文档中遇到的第一个<a>元素。若是想对多个元素进行匹配和操做,你可使用Document.querySelectorAll(),这个方法匹配文档中每一个匹配选择器的元素,并把它们的引用存储在一个假的array(NodeList)中。querySelectorAll的结果不会动态更新。

Document.getElementById()是旧的方法,没那么方便,而Document.querySelector()能够实现相同的功能。

Document.createTextNode():建立文本节点。栗子:var text = document.createTextNode('Hi');

若是咱们想移动 the paragraph with the link inside it to the bottom of the section, we could simply do this: sect.appendChild(linkPara);This moves the paragraph down to the bottom of the section. 你可能会觉得这会建立那个段落的副本,可是并无 — linkPara 是那个段落的惟一引用。 If you wanted to make a copy and add that as well, you'd need to use Node.cloneNode() instead.

操纵样式:可用HTMLElement.style属性添加内联样式。另外一种方法,添加的不是内联样式:在CSS里写好样式,而后在JavaScript里用Element.setAttribute()匹配样式。两种方式各有优缺点,选择哪一种取决于你本身。第一种方式简单,第二种方式更加纯粹(没有CSS和JavaScript的混合,没有内联样式这些被认为是很差的实践)。当你开始构建更大更复杂的应用时,你可能会更多地使用第二种方法,但这彻底取决于你本身。

注意: CSS样式的JavaSript属性版本以小写驼峰式命名法书写,而CSS样式的CSS版本用链接符号(好比,backgroundColor 对 background-color)。确保你不会混淆,不然就不能工做。

目前为止,咱们尚未作任何有用的事!使用JavaScript建立静态内容是毫无心义的你也能用HTML实现它,而不用JavaScript用JavaScript实现还更复杂,并且还有其它问题,好比不会被搜索引擎获取。

window.innerWidth和window.innerHeight是the width and height of the viewport。

window.onresize事件 : The window object has an event available on it called resize, which is fired every time the window is resized. 能够用来实现无论视口的大小是多少,应用程序都和它所在的视口同样大。

使用focus()方法能够在进入页面时自动聚焦。

相关文章
相关标签/搜索