Javascript
核心(ECMAScript)
Javascript
预留关键字 Reserved keywords
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Keywords
控制结构
条件表达式的三元操作符
|
|
switch 语句
- switch
- case
- break
- defult12345678910switch(action) {case 'draw':drawIt();break;case 'eat':eatIt();break;default:doNothing();}
对象
创建一个空对象
|
|
对象字面量(object literal), JSON 格式的核心语法(优先选择)
- 在对象实例中定义一个对象:12345678var obj = {name: "Carrot","for": "Max",details: {color: "orange",size: 12}}
对象的属性可以通过链式(chain)表示方法进行访问:
数组
特殊的属性——length(长度)属性
- 这个属性的值通常比数组最大索引大 1。
- 数组的长度是比数组最大索引值多一的数。
相关用法:
- forEach();
- push();
创建数组的传统方法
数组字面量(array literal)法(优先选择)
数组的长度是比数组最大索引值多一的数
访问不存在的数组,返回undefined
遍历数组 forEach():
如果想在数组后追加元素,只需要:
函数
|
|
- 函数实际上是访问了函数体中一个名为 arguments 的内部对象,这个对象就如同一个类似于数组的对象一样,包括了所有被传入的参数。
自定义对象
|
|
- 关键字 this:当使用在函数中时,this 指代当前的对象,也就是调用了函数的对象。如果在一个对象上使用点或者方括号来访问属性或方法,这个对象就成了 this。如果并没有使用“点”运算符调用某个对象,那么 this 将指向全局对象(global object)。
|
|
使用关键字 this 改进
|
|
- 单独调用fullName() 时会产生相同的问题,this指向全局变量,undefined
- new,它和 this 密切相关。它的作用是创建一个崭新的空对象,然后使用指向那个对象的 this 调用特定的函数。注意,含有 this 的特定函数不会返回任何值,只会修改 this 对象本身。new 关键字将生成的 this 对象返回给调用方,而被 new 调用的函数成为构造函数。习惯的做法是将这些函数的首字母大写,这样用 new 调用他们的时候就容易识别了。
再次改进
|
|
(最佳的方案)原型链
|
|
- 当你试图访问一个 Person 没有定义的属性时,解释器会首先检查这个 Person.prototype 来判断是否存在这样一个属性。所以,任何分配给 Person.prototype 的东西对通过 this 对象构造的实例都是可用的。
在程序中的任何时候修改原型(prototype)中的一些东西
|
|
可以给 JavaScript 的内置函数原型(prototype)添加东西。让我们给 String 添加一个方法用来返回逆序的字符串:
- PS: 这个方法可以随时制作自定义的方法
|
|
定义新方法也可以在字符串字面量上用(string literal)。
内部函数(可以访问父函数作用域中的变量,一个减少使用全局变量的好方法)
嵌套函数:可以访问父函数作用域中的变量
|
|
- 如果某个函数依赖于其他的一两个函数,而这一两个函数对你其余的代码没有用处,你可以将它们嵌套在会被调用的那个函数内部,这样做可以减少全局作用域下的函数的数量,这有利于编写易于维护的代码。
闭包(返回外部函数)
|
|
- makeAdder创建了一个新的 adder 函数,这个函数自身带有一个参数,它被调用的时候这个参数会被加在外层函数传进来的参数上。
- 与内嵌函数不同的是,外部函数被返回了,那么常识告诉我们局部变量“应该”不再存在。但是它们却仍然存在——否则 adder 函数将不能工作。也就是说,这里存在 makeAdder 的局部变量的两个不同的“副本”——一个是 a 等于5,另一个是 a 等于20。
|
|
每当 JavaScript 执行一个函数时,都会创建一个作用域对象(scope object),用来保存在这个函数中创建的局部变量。它和被传入函数的变量一起被初始化。这与那些保存的所有全局变量和函数的全局对象(global object)类似,但仍有一些很重要的区别,第一,每次函数被执行的时候,就会创建一个新的,特定的作用域对象;第二,与全局对象(在浏览器里面是当做 window 对象来访问的)不同的是,你不能从 JavaScript 代码中直接访问作用域对象,也没有可以遍历当前的作用域对象里面属性的方法。
所以当调用 makeAdder 时,解释器创建了一个作用域对象,它带有一个属性:a,这个属性被当作参数传入 makeAdder 函数。然后 makeAdder 返回一个新创建的函数。通常 JavaScript 的垃圾回收器会在这时回收 makeAdder 创建的作用域对象,但是返回的函数却保留一个指向那个作用域对象的引用。结果是这个作用域对象不会被垃圾回收器回收,直到指向 makeAdder 返回的那个函数对象的引用计数为零。
##### 闭包(Closure)补充知识
Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。
|
|
另一方面,在函数外部自然无法读取函数内的局部变量。
|
|
- 闭包的用途
|
|
- 思考题
|
|
|
|
内存泄漏(不要在匿名内部函数中使用变量、添加另外一个闭包)
解决因闭包而引入的循环引用:
- 不要在匿名内部函数中使用变量
- 添加另外一个闭包
|
|
这段代码创建了一个元素,当它被点击的时候变红,但同时它也会发生内存泄露。为什么?因为对 el 的引用不小心被放在一个匿名内部函数中。这就在 JavaScript 对象(这个内部函数)和本地对象之间(el)创建了一个循环引用。
解决办法1:不要使用e1变量
解决办法2:添加另外一个闭包
this
- Java属于编译期绑定,而JS属于 运行期绑定
- this和它声明环境无关,而完全取决于他的执行环境
|
|
bbb把aaa对象的say方法引用过来,引用的是一个方法而非一个对象,而aaa.say存储的是一个匿名函数,所以这种写法和以下代码并没有什么区别。
|
|
- 特殊情况:
和``` setInterval ``` 12345678910```javascriptvar aaa = {name: '哈利',getName: function () {setTimeout(function(){console.log(this.name);},100)}}
原来三行的输出会是什么?
答案:3个罗恩。
也就是说,三次this,指代的都是window对象。
稍微改写一下这个方法:
输出就又正常了。
ES6
类
使用 extends 创建子类
构造器:
- 构造器方法是一个特殊的类方法,其用于创建和初始化对象(用该类生成的)。一个类只能拥有一个名为 constructor 的方法,否则会抛出 SyntaxError 异常。
extends 关键字可以用在类声明或者类表达式中来创建一个继承了某个类的子类。
同样也可以用于原有的原型继承的“类”:
使用 super 引用父类
super 关键字可以用来调用其父类的构造器或者类方法
文档对象模型(DOM)
浏览器对象模型(BOM)
Javascript写成类插件
|
|
JavaScript常错
getElementById 获取变量
但如果事先定义一个变量,例如
|
|
然后就会报错,说item为null。
如果去掉引号就好了。。
即:
不加引号,这个itemid就是变量,加上引号,这就是字符串常量。电脑就去找ID为ItemId的元素。自然是null
javascript 陷阱集
- 考作用域
|
|
|
|
- 考声明提前
|
|
- 考 this
|
|
- 制造干扰因素的版本
|
|
- 分号陷阱
|
|
- 小数相加
|
|