由于私有和特权成员在函数的内部,因此它们会被带到函数的每个实例中。
公有的原型成员是对象蓝图的一部分,适用于通过new关键字实例化的该对象的每个实例
静态成员只适用于对象的一个特殊实例
Function 对象(类)
ECMAScript 最令人感兴趣的可能莫过于函数实际上是功能完整的对象。
Function 类可以表示开发者定义的任何函数。是个函数构造器
构造函数.prototype = 原型对象
原型对象.constructor = 构造函数(模板)
原型对象.isPrototypeof(实例对象) 判断实例对象的原型 是不是当前对象
1 |
|
元素对象常用属性:
- obj.innerHTML;
- obj.outerHTML;
- obj.innerText;
- obj.textContent;
- obj.tagName;
1 | <p>hello world!<span>你好</span></p> |
1 | <script> |
判断IE与非IE浏览器:
1
2 if(document.all) alert('IE');
else alert("not IE");//用来判断IE与非IE浏览器
setTimeout
的定时器值推荐最小使用16.7ms的原因(16.7 = 1000 / 60, 即每秒60帧)。
1 | //匿名函数通过引用来调用 |
标签声明:
JavaScript
中的标签就是一个标识符,声明如下:
一个标识符后面跟一个冒号”:”。你可以在任何一个语句前面加上这样的标签。以使得该语句被“标签化”,例如:
1 | this_is_a_label: |
除了单一的语句外,标签也可以用于由大括号表示的符合语句,例如:
1 | label_statments: { |
在JS中有三种方法会涉及“初始化对象实例”的问题:
其一,是通过在构造器中利用this引用来初始化
其二,是通过构造原型实例来初始化
其三,是通过Object.create()并使用属性描述符的方式来构建对象并初始化
当参数表为空与没有参数表是一致的。因此下面两行代码是等意的:
1 | obj = new constructor; |
但是,我们不能认为constructor
后面的括号是函数调用的括号。因为如果这是函数调用的括号,那么下面的代码就应该是合理的了(但事实上,这行代码对于构造器来说是错误的用法):
1 | obj = new (constructor()); |
所以,不能错误地认为:new运算符是“产生对象实例,并调用constructor函数”——尽管看起来是这样
但是,如果我们的确不打算让new后面的函数作为构造器,而只是作为函数使用,可以这么做:
1 | //将foo视为普通函数 |
函数的提升(hoisting)
函数声明的行为并不等同于命名函数表达式,其区别在于提升(hoisting)行为,看下面例子:
1 | <script type="text/javascript"> |
Call和apply
apply
可以使用数组字面量(array literal),如 fun.apply(this, ['eat', 'bananas'])
,或数组对象, 如 fun.apply(this, new Array('eat', 'bananas'))
。
1 | Function.prototype.construct = function (aArgs) { |
可以通过func1.call(this, arg1, arg2)
; 或者 func1.apply(this, [arg1, arg2])
; 来调用。其中 this 是你想指定的上下文,他可以任何一个 JavaScript 对象(JavaScript 中一切皆对象),call 需要把参数按顺序传递进去,而 apply 则是把参数放在数组里。
1 | location.hash=anchorname |
字面量对象
1 | //不管用什么方式调用它(使用new或直接调用),它都会返回一个实例对象: |
这种模式的问题是会丢失原型,因此在Waffle()的原型上的成员不会被继承到这些对象中。
Array()
构造函数的“陷阱”
我们对new Array()敬而远之还有一个原因,就是为了避免构造函数带来的陷阱。
如果给Array()构造函数传入一个数字,这个数字并不会成为数组的第一个元素,而是设置了数组的长度。也就是说,new Array(3)创建了一个长度为3的数组,而不是某个元素是3。如果你访问数组的任意元素都会得到undefined,因为元素并不存在。
1 | // 含有1个元素的数组 |
JavaScript使用函数来管理作用域,在一个函数内定义的变量称作“本地变量”,本地变量在函数外部是不能被访问的。
任何不通过var声明的变量都会成为全局对象的一个属性
另一种创建全局变量的反模式,就是在var声明中使用链式赋值的方法。在下面这个代码片段中,a是局部变量,但b是全局变量,而作者的意图显然不是这样:
1 | // 反模式 |
对象有两种类型的成员:实例成员和原型成员。实例成员直接存在于实例自身,而原型成员则从对象原型继承:1
2
3
4var book = {
title: "High Performance Js",
publisher: "Yahoo!Press"
};
此代码中,book对象有两个实例成员:title
和publisher
。
js给变量赋null值的作用在于:
就是赋值一个空指针,不赋值也可以,只是赋值了让人更容易理解这个变量是用来准备存放对象的,也方便调错。
style.display = ""
;是清除display样式,display将使用默认值(块元素会变成block,内联元素会变成inline)style.display="none"
; 中“none”是一个值,表示元素将隐藏
querySelector(IE8部分支持)
该方法返回满足条件的单个元素。按照深度优先和先序遍历的原则使用参数提供的CSS选择器在DOM进行查找,返回第一个满足条件的元素。
1 | element = document.querySelector('div#container');//返回id为container的首个div |
setTimeout()
是属于 window 的 method
1 | var obj = { |
用 document.readyState == "complete"
判断页面是否加载完成
编写高质量代码
1 | var my = {};//把多个全局变量都追加在一个名称空间下,将显著降低与其他应用程序产生冲突的概率 |
在一个函数中的任何位置定义的变量在该函数中的任何地方都可见。
判断是否是https
1 var isHttps = location.protocol.indexOf('https') > -1;
Location 对象包含有关当前 URL 的信息。
Location 对象属性
属性 描述1
2
3
4
5
6
7
8hash 设置或返回从井号 (#) 开始的 URL(锚)。
host 设置或返回主机名和当前 URL 的端口号。
hostname 设置或返回当前 URL 的主机名。
href 设置或返回完整的 URL。
pathname 设置或返回当前 URL 的路径部分。
port 设置或返回当前 URL 的端口号。
protocol 设置或返回当前 URL 的协议。
search 设置或返回从问号 (?) 开始的 URL(查询部分)。
Promise
所谓Promise,字面上可以理解为“承诺”,就是说A调用B,B返回一个“承诺”给A,然后A就可以在写计划的时候这么写:当B返回结果给我的 时候,A执行方案S1,反之如果B因为什么原因没有给到A想要的结果,那么A执行应急方案S2,这样一来,所有的潜在风险都在A的可控范围之内了。
上面这句话,翻译成代码类似:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20var resB = B();
var runA = function() {
resB.then(execS1, execS2);
};
runA();
var resB = B();
var resC = C();
...
var runA = function() {
reqB
.then(resC, execS2)
.then(resD, execS3)
.then(resE, execS4)
...
.then(execS1);
};
runA();
该新特性属于 ECMAScript 2015(ES6)规范:
Promise 对象用来进行延迟(deferred) 和异步(asynchronous ) 计算.。一个 Promise 处于以下四种状态之一:
pending: 初始状态, 非 fulfilled 或 rejected.
fulfilled: 成功的操作.
rejected: 失败的操作.
settled: Promise已被fulfilled或rejected,且不是pending
new Promise(executor);
new Promise(function(resolve, reject) { … });
executor
函数对象,带有两个实参 resolve 和 reject. 第一个参数用来完成(fulfill)当前promise,第二个参数则用来拒绝(reject). 一旦我们的操作完成即可调用这些函数.
promise必须实现then方法(可以说,then就是promise的核心),而且then必须返回一个promise,同一个promise的then可以调用多次,并且回调的执行顺序跟它们被定义时的顺序一致
then方法接受两个参数,第一个参数是成功时的回调,在promise由“等待”态转换到“完成”态时调用,另一个是失败时的回调,在promise由 “等待”态转换到“拒绝”态时调用。同时,then可以接受另一个promise传入,也接受一个“类then”的对象或方法,即thenable对象。
Object和Function都是构造函数,而所有的构造函数的都是Function的实例对象. 因此Object是Function的实例对象
实例对象的constructor([Function: Object])
的prototype是对象{}。构造函数的prototype( {} )的constructor是[Function Object]
继承函数的原理莫过于复制类的方法和属性。因此,只要做到这点,就可以实现类的继承了。可以在上面的代码中看见,我们通过遍历prototype来获取原型链中定义的方法和属性。通过apply调用父类的构造器进行构造器中属性和方法的复制
1 | function base (d, b, a) { |
使用示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15function People () {
this.name = "Yorhom";
}
People.prototype.getName = function () {
return this.name;
};
function Student () {
base(this, People, []);
}
var yorhom = new Student();
// "Yorhom"
alert(yorhom.getName());
Each function has two properties: length and prototype
property是DOM中的属性,是JavaScript里的对象;
attribute是HTML标签上的特性,它的值只能够是字符串;
1 | Array.prototype.map(function(currentValue,index,array){}) |
map 方法会给原数组中的每个元素都按顺序调用一次 callback 函数。callback 每次执行后的返回值组合起来形成一个新数组。
`
Array.prototype.forEach(function(currentVal,idx,array){})
callback 函数会被依次传入三个参数:
数组当前项的值
数组当前项的索引
数组对象本身
函数也是对象,可以往函数上添加属性。将全局变量添加到函数的属性上,可以使之成为局部变量,减少命名冲突问题。