1.JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里
2.什么是闭包
闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分
闭包的特点:
1)作为一个函数变量的一个引用,当函数返回时,其处于激活状态。
2) 一个闭包就是当一个函数返回时,一个没有释放资源的栈区。
简单的说,Javascript允许使用内部函数—即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。
- 什么是跨域?跨域请求资源的方法有哪些?
1)什么是跨域
由于浏览器同源策略,凡是发送请求的url的协议、域名、端口 三者之间任意一个与当前地址不同即为跨域
- 网络协议不同,如http协议访问https协议
- 端口不同,如80端口访问8080端口
- 域名不同,如qianduanblog.com访问baidu.com
- 子域名不同,如abc.qianduanblog.com访问def.qianduanblog.com
- 域名和域名对应ip,如www.a.com访问20.205.28.90
2)跨域请求资源的方法
1》porxy代理
2》CORS[Cross-Origin Resource Sharing]
定义和用法:是现代浏览器支持跨域资源请求的一种最常用的方式。
使用方法:一般需要后端人员在处理请求数据的时候,添加允许跨域的相关操作。如下:
3》jsonp
定义和用法:通过动态插入一个script标签。浏览器对script的资源引用没有同源限制,同时资源加载到页面后会立即执行(没有阻塞的情况下)
特点:通过情况下,通过动态创建script来读取他域的动态资源,获取的数据一般为json格式。
缺点:
1、这种方式无法发送post请求(这里)
2、另外要确定jsonp的请求是否失败并不容易,大多数框架的实现都是结合超时时间来判定。
4.面向对象的程序设计
1)对象的定义
ECMA-262把对象定义为:无序属性的集合,其属性可以包含基本值、对象或者函数
严格来说,这就相当于说对象是一组没有特定顺序的值
对象的每个属性或方法都有一个名字,而每个名字都映射到一个值
我们可以把ECMAScript对象想象成散列表
2)属性类型
数据类型
configurable 表示是否通过delete删除属性从而重新定义属性
enumerable 表示是否通过for-in循环返回属性
writeable 表示是否修改属性的值
value 包含这个属性的值,读取属性值的时候,从这个位置读;写入属性值的时候,把这新值保存在这个位置,这个特性的默认值为 undefined
修改属性默认的特性,必须使用ES5的Object.defineProperty()
接收三个参数:属性所在的对象、属性的名字和一个描述符对象
其中描述符(descriptor)对象的属性必须是:configurable、enumerable、writable和value
设置其中一或多个值,可以修改对应的特性值
把configurable设置为false,表示不能从对象中删除属性
如果对这个属性调用delete,则在非严格模式下什么也不会发生,而在严格模式下会导致错误
而且,一旦把属性定义为不可配置的,就不能再把它变回可配置了
此时,再调用Object.defineProperty()方法修改除writable之外的特性,都会导致错误
在调用**Object.defineProperty()**方法时,如果不指定,configurable、enumerable和writable特性的默认值都是false
访问器属性
configurable 表示能否通过delete删除属性从而重新定义属性
enumerable 表示能够通过for-in循环返回属性
get 在读取属性时调用的函数,默认值为undefined
set 在写入属性时调用的函数,默认值为undefined
访问器属性不能直接定义,必须使用Object.defineProperty()来定义
读取属性的特性
Object.getOwnPropertyDescriptor()
3)创建对象
工厂模式
考虑到在ECMAScript中无法创建类,开发人员就发明了一种函数,用函数来封装以特定接口创建对象的细节
函数createPerson()能够根据接受的参数来构建一个包含所有必要信息的Person对象
工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型)
构造函数模式
ECMAScript中的构造函数可用来创建特定类型的对象
像Object和Array这样的原生构造函数,在运行时会自动出现在执行环境中。
此外,也可以创建自定义的构造函数,从而定义自定义对象类型的属性和方法
相比较工厂方法,构造方法Person()函数,除了与createPerson()相同部分,还有以下不同之处
- 没有显式地创造对象
- 直接将属性和方法赋给了this对象
- 没有return对象
按照惯例,构造函数始终都应该以一个大写字母开头,而非构造函数则应该以一个小写字母开头
这个做法借鉴自其他OO语言,主要是为了区别于ECMAScript中的其他函数
因为构造函数本身也是函数,只不过可以用来创建对象而已
要创建Person的新实例,必须使用new操作符
用这种方式构造函数实际会经历以下4个步骤:
- 创建一个对象
- 将构造函数的作用域赋给新对象(因此this就指向了这个新对象)
- 执行构造函数中的代码(为这个新对象添加属性)
- 返回新对象
constructor(构造函数)属性
对象的 constructor属性最初是用来标识对象类型的
alert(person1.constructor == Person); //true
alert(person2.constructor == Person); //true
检测对象类型instanceof
alert(person1 instanceof Object); //true
alert(person1 instanceof Person); //true
alert(person2 instanceof Object); //true
alert(person2 instanceof Person); //true
创建自定义的构造函数意味着将来可以将它的实例标识为一种特定的类型;而这正是构造函数模式胜过工厂模式的地方
person1和person2之所以同时是Object的实例,是因为所有对象均继承自Object
原型模式
每个函数都有一个prototype(原型)属性
这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法
如果按照字面意思来理解,那么prototype就是通过调用构造函数而创建的那个对象实例的原型对象
5.基本类型和引用类型
5种基本数据类型:Undefined、Null、Boolean、Number和String
这5种基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值
引用类型的值是保存在内存中的对象
在操作对象时,实际上是在操作对象的引用而不是实际的对象。为此,引用类型的值是按引用访问的
当复制保存着对象的某个变量时,操作的是对象的引用。但在为对象添加属性时,操作的是实际的对象
检测类型
var s = “Nicholas”;
var b = true;
var i = 22;
var u;
var n = null;
var o = new Object();
alert(typeof s); //string
alert(typeof i); //number
alert(typeof b); //boolean
alert(typeof u); //undefined
alert(typeof n); //object
alert(typeof o); //object
null的typeof为object
instanceof操作符
result= variable instanceof constructor
typeof操作符
typeof检测函数时,该操作符会返回“function”
6.传递参数
对象是按值传递的
7.数组
1)检测数组
join()方法重现了toString()方法的输出
如果数组中的某一项的值是null或者undefined,那么该值在join(),toLocaleString()、toString()和valueOf()方法返回的结果中以空字符串表示
2)栈方法
栈是一种LIFO(Last-In-First-Out后进先出)的数据结构,也就是最新添加的项最早被移除
栈中项的插入(叫做推入)和移除(叫做弹出),只发生在一个位置——栈的顶部
数组通过push()和pop()方法,实现类似栈的行为
push() 接受任意数量的参数,把它们逐个添加到数组尾部,并返回修改后数组的长度
pop() 从数组末尾移除最后一项,减少数组的length值,然后返回移除的项
3)队列方法
队列是一种FIFO(First-In-First-Out先进先出)的数据结构,队列在队列的末端添加项,从列表的前端移除项
shift() 移除数组中的第一项并返回该值,同时将数组长度减1
数组通过shift()和push()方法,实现类似队列的行为
unshift() 在数组前端添加任意个项并返回新数组的长度
同时使用unshift()和pop()方法,可以从相反的方向来模拟
4)重排序方法
reverse() 反转数据项的顺序
sort() 按升序排列数组项——即最小值位于最前面,然后比较得到字符串,以确定如何排序
compare 后者减前者大于零 降序
reverse()和sort()方法的返回值是经过排序之后的数组
5)操作方法
concat()基于当前数组中所有项创建一个新数组
- 这个方法会先创建当前数组一个副本,然后将接受到的参数添加到这个副本末尾,最后返回新构建的数组
- 如果传递给concat()方法的是一个或多个数组,则该方法会将这些数组中的每一项添加到结果数组中
- 如果传递的值不是数组,这些值就会简单的添加到结果数组的末尾
slice() 基于当前数组一个或多个创建一个新的数组
- 可以接受一个或两个参数,即要返回项的起始和结束位置
- 一个参数时,返回从该参数指定位置到当前数组末尾的所有项
- 两个参数时,返回起始和结束位置之间的项,含头不含尾
- slice()方法中有一个负数,则用数组长度加上该数来确定相应位置
- 如果结束位置小于起始位置,则返回空数组
splice() 向数组中部插入项,方法有三种 - 删除:可以删除任意数量的项,只需要指定2个参数:要删除的第一项的位置和要删除的项数
splice(0,2)会删除数组的前两项 - 插入:可以向指定的位置插入任意数量的项,只需提供3个参数:起始位置、0(要删除的项数)和要插入的项
若要插入多项,可以再传入第四、第五以至任意多的项 - 替换:可以向指定的位置插入任意数量的项,且同时删除任意数量的项,只需提供3个参数:起始位置、要删除的项数和要插入的任意数量的项, 插入的项数不必与删除的项数相等
splice()方法始终都会返回一个数组,该数组包含从原始数组中删除的项(如果没有删除任何项,就返回一个空数组)
6)位置方法
indexOf() 和 lastIndexOf() 都接受两个参数:要查找的项和(可选的)表示查找起点位置的索引
indexOf() 从数组开头(位置0)开始向后查找
lastIndexOf() 从数组的末尾开始向前查找
这两个方法都返回要查找的项在数组里面的位置,或者没有找到的情况下返回-1
在比较第一个参数和数组中的每一项时,会使用全等操作符
7)迭代方法
5个迭代方法,都接受两个参数:要在每一项上运行的函数和(可选值)运行该函数的作用域对象——影响this的值
- every() 对数组中的每一项运行给定的函数,如果该函数对每一项都返回true,则返回true
- filter() 对数组中的每一项运行给定的函数,返回该函数会返回true的项组成的数组
- forEach() 对数组中的每一项运行给定的函数,这个方法没有返回值
- map() 对数组中的每一项运行给定的函数,返回每次函数调用的结果组成的数组
- some() 对数组中的每一项运行给定的函数,如果该函数对任一项返回true,则返回true
以上方法都不会修改数组中的包含的值
最相似的是every()和some(),它们都用于查询数组中的项是否满足某个条件
8)并归方法
2个归并方法,reduce()和reduceRight()都会迭代数组的所有项,然后构建一个最终返回值
- reduce() 从数组的第一项开始,逐个遍历到最后
- reduceRight() 从数组的最后一项开始,向前遍历到第一项
都接受两个参数:一个在每一项上调用的函数和(可选的)作为归并基础的初始值
传给reduce()和reduceRight()的函数接收4个参数:前一个值、当前值、项的索引和数组对象
https://www.jianshu.com/p/e375ba1cfc47
includes() 判断一个数组是否包含一个指定的值,如果是返回true,否则false
接受两个参数:需要查找的元素值和(可选的)表示查找起点位置的索引
8.Function方法
函数是对象,函数名是指针
函数其实是对象,因此函数名实际上是一个指向函数对象的指针,不会与某个函数绑定
通常使用函数申明语法定义
使用不带圆括号的函数名是访问函数指针,而非调用函数
没有重载——申明两个同名函数,而结果则是后面的函数覆盖了前面的函数
函数声明和函数表达式
解析器 通过一个函数声明提升的过程 作为值得函数,会报错,需要先申明
call()和apply()
相同点:这两个方法的作用是一样的
都是在特定的作用域中调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的作用域
一般来说,this总是指定调用某个方法的对象,但是使用call()和apply()方法时,就会改变this的指向
不同点:接受参数的方法不同
apply() 接受两个参数,一个是函数运行的作用域(this),另一个是参数数组
语法:apply([thisObj [,argArray] ]);,调用一个对象的一个方法,2另一个对象替换当前对象。
call() 第一个参数和apply()方法一致,但是传递给函数的参数必须列举出来
语法:call([thisObject[,arg1 [,arg2 [,…,argn]]]]);,应用某一对象的一个方法,用另一个对象替换当前对象。
使用call()(或apply())来扩充作用域的最大好处,就是对象不需要与方法有任何耦合关系
9.RegExp类型
ECMAScript通过RegExp类型来支持正则表达式
每个正则表达式都可带有一或多个表示(flags),用以标明正则表达式的行为
正则表达式的匹配模式支持下列3个标志
- g: 表示全局(global)模式
- i: 表示不区分大小写
- m:表示多行模式,即在到达