1.module.exports 初始值为一个空对象 {}
2.exports 是指向的 module.exports 的引用
3.require() 返回的是 module.exports 而不是 exports
常用写法:exports = module.exports = {...} 等价于 module.exports = {...}和exports = module.exports
原理:module.exports 指向新的对象时,exports 断开了与 module.exports 的引用,那么通过 exports = module.exports 让 exports 重新指向 module.exports。
npm i express --save/npm i express -S (安装 express,同时将 "express": "^4.14.0" 写入 dependencies )
npm i express --save-dev/npm i express -D (安装 express,同时将 "express": "^4.14.0" 写入 devDependencies )
npm i express --save --save-exact (安装 express,同时将 "express": "4.14.0" 写入 dependencies )
第三种方式将固定版本号写入 dependencies,建议线上的 Node.js 应用都采取这种锁定版本号的方式,因为你不可能保证第三方模块下个小版本是没有验证 bug 的,即使是很流行的模块。
一段js在执行之前,浏览器在全局环境会先做一些准备工作:
1.给变量、函数表达式进行声明,默认赋值为undefined;
- 给this赋值;
3.给函数声明赋值;
4.函数每次被调用,都会产生一个新的执行上下文环境,函数体内的语句在执行之前,arguments变量和函数的参数都已经被赋值
以上这些准备工作就称之为执行上下文或者执行上下文环境;
通俗定义:在执行代码之前,把将要用到的所有的变量都事先拿出来,有的直接赋值了,有的先用undefined占个空。
执行上下文栈
正如我们所知,执行全局代码时会产生一个执行上下文环境,每次调用函数又会产生一个执行上下文环境。当函数调用完成时,这个上下文环境以及其中的数据都会被消除,再回到全局上下文环境。处于活动状态的执行上下文环境只能有一个。其实这就是一个压栈出栈的过程,称之为执行上下文栈。
|| 和 &&
只要"||"前面为true,无论"||"后面是true还是false,结果都返回"||"前面的值
只要"&&"前面为false,无论"&&"后面是true还是false,结果都返回"&&"前面的值
call和apply:为了动态改变this的值而存在的,当一个对象没有某个方法,别的对象有这个方法,我们又不想对这个对象重新定义一个一样的方法,我们就可以通过call或者apply来使用其他对象的方法来操作。
对象的含义:带有属性和方法的特殊数据类型。
函数和对象之间,不仅仅是包含和被包含的关系,有一点鸡生蛋档蛋生鸡的逻辑。
对象都是通过函数来创建的,函数又是一种对象,像var obj = {name:"xixi",age:12}这种新建对象的方法,其实是一种语法糖来的,本质还是通过var obj = new Object();obj.name = "xx"...这种函数的方式来创建。
每个函数都有一个叫做prototype的属性,这个prototype的属性值是一个对象,该对象默认的只有constructor的属性,指向这个函数本身。每个对象都有一个proto,并且proto指向创建该对象的函数的prototype。
比如:
function Fn(){} var fn = new Fn() Fn是一个函数,fn对象是从Fn()函数new出来的,这样fn对象就可以调用Fn.prototype中的属性。因为每一个对象都有一个隐藏的属性“proto”,这个属性引用了创建这个对象的函数的prototype。即:fn.proto === Fn.prototype
对象是被函数创建的,函数是被Function(函数)创建的。Function是被自身创建的。
js中继承是通过原型链来体现的。访问一个对象的属性时,先在基本属性中查找,如果没有,再沿着proto这条链向上找,这就是原型链。可以用hasOwnProperty函数来判断一个对象的属性到底是基本属性还是继承属性。但是hasOwnProperty是从哪里来的呢?它是从Object.prototype中来的。
由于所有的对象的原型链都会找到Object.prototype,因此所有的对象都会有Object.prototype的方法,这就是所谓的“继承”。每个函数都有call,apply方法,都有length,arguments,caller等属性,这些都是继承的。函数由Function函数创建,因此继承了Function.prototype中的方法。
数组去重:
数组排序:数组的sort()方法默认是把所有的元素先转化为字符串再排序,而字符串的排序是根据ASCLL码排序的,小写字母a的ASCLL码排在大写字母之后。
冒泡排序:
快速排序:
其他排序方法:
通常规定,对于两个元素x和y,如果认为x < y,则返回-1;如果x == y,则返回0;如果x > y;则返回1。这样排序算法就不用关心具体的比较过程,而是根据比较结果直接排序。但是需要注意的事这个方法需要忽略大小写。
原型对象的结构
Function.prototype = {
constructor : Function,
proto : parent prototype (原型指针,指向上一级的原型对象),
some prototype properties : 一些原型属性
}
解释:函数的原型对象的constructor默认指向函数本身,原型对象除了有原型属性外,为了实现继承,还有一个原型链指针proto,该指针指向上一层的原型对象,而上一层的原型对象的结构依然类似,这样利用proto一直指向Object的原型对象上,而Object的原型对象Object.prototype.proto = null表示原型链的最顶端,如此便形成了JavaScript的原型链继承,同时也结识了为什么所有的JavaScript对象都具有Object的基本方法。