JS 基础
数据类型
JavaScript的数据类型分为两类,原始类型和对象类型
原始类型
- 数字
- 字符串
- 布尔值
- null
- undefined
除了这些原始类型外其他的都是对象类型
null 和 undefined 区别
null用来描述空值;undefined用来表明变量没有初始化
typeof null => object
typeof undefined => undefined
Number 常用函数
-
Number.isNaN(value)
- 判断传入的值是否为NaN
-
number.toFixed(digits)
- 指定保留几位小数
-
number.toExponential(digits)
- 指数表示法,指定保留几位小数
-
number.toPrecision(precision)
- 以指定的精度返回该数值对象的字符串表示
String 常用函数
-
str.charAt(index)
- charAt() 方法返回字符串中指定位置的字符。
-
str.concat(string2, string3[, ..., stringN])
- concat() 方法将一个或多个字符串与原字符串连接合并,形成一个新的字符串并返回。
-
str.indexOf(searchValue[, fromIndex])
- indexOf() 方法返回指定值在字符串对象中首次出现的位置。从 fromIndex 位置开始查找,如果不存在,则返回 -1。
-
str.slice(beginSlice[, endSlice])
- slice()方法提取字符串的一部分,并返回这个新的字符串
-
str.split([separator][, limit])
- split() 方法通过把字符串分割成子字符串来把一个 String 对象分割成一个字符串数组
Array 常用函数
-
array.splice(start, deleteCount[, item1[, item2[, ...]]])
- splice() 方法从start处开始删除deleteCount个元素,并在该位置插入新的元素。
-
array.forEach(callback[, thisArg])
- forEach() 方法让数组的每一项都执行一次给定的函数
-
array.map(callback[, thisArg])
- map() 方法返回一个由原数组中的每个元素调用一个指定方法后的返回值组成的新数组。
-
arr.filter(callback[, thisArg])
- filter() 方法使用指定的函数测试所有元素,并创建一个包含所有通过测试的元素的新数组。
-
arr.some(callback[, thisArg])
- some() 方法测试数组中的某些元素是否通过了指定函数的测试。
-
arr.every(callback[, thisArg])
- every() 方法测试数组的所有元素是否都通过了指定函数的测试。
-
arr.reduce(callback,[initialValue])
- reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始合并,最终为一个值。
- callback(previousValue, currentValue, index, array)
- 如果 initialValue 在调用 reduce 时被提供,那么第一个 previousValue 等于 initialValue ,并且currentValue 等于数组中的第一个值;如果initialValue 未被提供,那么previousValue 等于数组中的第一个值,currentValue等于数组中的第二个值。
函数作用域
变量在声明他们的函数体以及这个函数体嵌套的任意函数体内部都是有定义的
声明提前
由于JavaScript函数作用域的特性,变量甚至在声明之前就已经可用。JavaScript函数中声明的所有变量都被“提前”至函数体的顶部(只是声明被提前了,并不代表赋值也被提前
作用域链
每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。
当代码在一个环境中执行时,会创建变量对象的一个作用域链。
作用域链的前端,始终是当前执行的代码所在环境的变量对象。作用域链中下一个变量对象来自包含环境,再下一个变量对象来自下一个包含环境。这样,一直延续到全局执行环境。全局执行环境的变量对象始终是作用域链的最后一个对象。
作用域链的用途是保证对执行环境有权访问的所有变量的有序访问。
闭包
闭包是指有权访问另一个函数作用域的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量
简单理解:函数执行完以后,函数中的变量没有被销毁,被它返回的子函数调用。
闭包有三个特性
- 函数嵌套函数
- 函数内部可以引用外部的参数和变量
- 参数和变量不会被垃圾回收机制回收
使用闭包的好处
- 希望一个变量长期驻扎在内存中,不被回收
- 避免全局变量的污染
- 私有成员的累加
this 关键字
this是JavaScript的一个关键字。
它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。
随着函数使用场合的不同,this的值会发生变化。但是有一个总的原则,那就是this指的是,调用函数的那个对象。
-
纯粹的函数调用
这是函数的最通常用法,属于全局性调用,因此this就代表全局对象Global
var x = 1; function test() { alert(this.x); } test(); // 1 ---------------------------------------------------- var x = 1; function test() { this.x = 0; } test(); alert(x); // 0
-
作为对象方法的调用
函数还可以作为某个对象的方法调用,这是this就是指这个上级对象
function test() { alert(this.x); } var o = { x: 1 }; o.m = test; o.m(); // 1
-
作为构造函数调用
所谓构造函数,就是通过这个函数生成一个新对象。这时,this就指这个新对象。
function test() { this.x = 1; } var o = new test(); alert(o.x); // 1
-
apply调用
apply()是函数对象的一个方法,它的作用是改变函数的调用对象,它的第一个参数就表示改变后的调用这个函数的对象。因此,this指的就是这第一个参数。
var x = 0; function test() { alert(this.x); } var o = {x: 1}; o.m = test; o.m.apply(); // 0 o.m.apply(o); // 1
定义类
-
构造函数法
主要缺点:用到了this和prototype,较为复杂
// 构造函数 function Cat() { this.name = "lance"; } Cat.prototype = { constructor: Cat, makeSound: function() { alert("miao~"); } } var cat = new Cat(); alert(cat.name); // 'lance' cat.makeSound(); // 'miao~'
-
Object.create() 法
缺点: 不能实现私有属性和私有方法,实例对象之间也不能共享数据。
var Cat = { name: "lance", makeSound: function() {alert("miao~")} }; var cat = Object.create(Cat); alert(cat.name); cat.makeSound();
类的继承
现在有一个Animal对象的构造函数
function Animal() {
this.species = "Animal";
}
还有一个Cat对象的构造函数
function Cat(name, color) {
this.name = name;
this.color = color;
}
需要使Cat继承Animal
-
构造函数绑定
function Cat(name, color) { // 在子类的构造函数中,调用父类的构造函数,将父类的方法添加到this上 Animal.apply(this, arguments); this.name = name; this.color = color; } // 使子类的的原型指向父类的原型 Cat.prototype = Object.create(Animal); Cat.prototype.constructor = Cat; var cat = new Cat("mimi", 'yellow'); alert(cat.species); // Animal
-
prototype模式
第二种方法更常见,使用prototype模式
如果Cat的prototype对象,指向一个Animal对象,那么所有Cat的实例,都能继承Animal了
Cat.prototype = new Animal(); Cat.prototype.constructor = Cat; var cat = new Cat("mimi", 'yellow'); alert(cat.species); // Animal
Ajax
异步JavaScript和XML
AJAX包括以下几个步骤
- 实例化XMLHttpRequest对象
- 用open方法指定HTTP动词,请求的网址,是否异步
- 绑定想用HTTP请求状态变化的函数
- 发送HTTP请求
- 获取异步调用返回的数据
- 使用JavaScript和DOM实现局部刷新
readyState值
- 0,对应UNSENT, 表示XMLHttpRequest实例已经生成,但是open()方法还没有被调用。
- 1,对应常量OPENED,表示send()方法还没有被调用,仍然可以使用setRequestHeader(),设定HTTP请求的头信息。
- 2,对应常量HEADERS_RECEIVED,表示send()方法已经被执行,并且头信息和状态码已经收到。
- 3,对应常量LOADING,表示正在接收服务器传来的body部分的数据
- 4,对应常量DONE,表示服务器数据已经完全接收,或者本次接收已经失败
事件监听端口
- onloadstart: 请求发送
- onprogress: 正在发送和加载数据
- onabort:请求被终止
- onerror:请求失败
- onload:请求成功完成
- ontimeout:用户指定的时限到期,请求还未完成
- onloadend:请求完成,不管成果或失败
上传进度事件
var xhr = new XMLHttpRequest();
xhr.open("POST", "/server", true);
xhr.onload = function() {};
xhr.upload.onprogress = funciton(e) {
if(e.lengthComputable) {
console.log(e.loaded);
console.log(e.total);
}
}
xhr.send(new FormData());
文件上传
FormData
-
File API
var file = document.getElementById("test-input").files[0]; var xhr = new XMLHttpRequest(); xhr.open("POST", "myserver/uploads"); xhr.setRequestHeader("Content-Type", file.type); xhr.send(file);
JSONP
JSON
JSON是一种基于文本的数据交换方式,或者叫做数据描述格式。
- 优点
- 基于纯文本,跨平台传递及其简单
- JavaScript原生支持,后台语言几乎全部支持
- 轻量级数据格式,占用字符数量极少,特别适合互联网传递
- 可读性强
JSONP
JSONP只支持GET方法
首先在浏览器端注册一个callback
然后把callback的名字追加在要跨域请求的url上通过 <script>传给服务器。
服务器得到callback的数值后,生成js脚本 callback(data)
。(也就是说,服务器端的js脚本是动态生成的)
浏览器端运行服务器端传回来的js脚本
常见状态码
- 200,OK,访问正常
- 301,Moved Permanently,永久移动
- 302,Move temporarily,暂时移动
- 304,Not Modified,未修改
- 307,Temporary Redirect,暂时重定向
- 401,Unauthorized,未授权
- 403,Forbidden,禁止访问
- 404,Not Found,未发现指定网址
- 500,Internal Server Error,服务器发生错误
客户端存储
localStorage 和 SessionStorage都是持久化关联数组,两者的区别在于存储有效期和作用域不同:数据可以存储多长时间以及谁拥有数据的访问权。
localstorage
通过localStorage存储的数据是永久性的,除非刻意删除存储的数据,否则数据将一直保留在用户的电脑上,永不过期。
localStorage的作用域是限定在文档源级别的。文档源是通过协议,主机名以及端口三者来实现的。
sessionStorage
sessionStorage的有效期和存储数据的脚本所在的窗口或浏览器标签页是一样的。也就是说,一旦窗口或者标签页被永久关闭了,那么所有通过sessionStorage存储的数据也都被删除了。
sessionStorage的作用域也被限定在窗口中。如果同源的文档渲染在不同的浏览器标签中,那么它们相互之间拥有的是各自的sessionStorage数据,无法共享。
cookie
cookie是存储在浏览器的少量数据,cookie数据会自动在Web浏览器和Web服务器之间传输。
cookie默认的有效期很短暂,它只能持续在web浏览器的会话期间,一旦用户关闭浏览器,cookie保存的数据就丢失了,如果想要延长cookie的有效期,可以通过设置max-age属性(单位是s)
cookie的作用域是通过文档源和文档路径来确定的。该作用域是通过cookie的domain和path配置的。默认情况下,cookie和创建它的Web页面有关,并对该Web页面以及和该Web页面同目录或者子目录的其他web页面可见。
局限性
不允许浏览器保存超过300个cookie,每个web服务器保存的cookie不超过20个,每个cookie的大小都能超过4kb
由于cookie的实现机制,一旦服务器端向客户端发送了设置cookie的意图,除非cookie过期,否则客户端每次请求都会发送这些cookie到服务器端,一旦设置的Cookie过多,将会导致报头较大。大多数cookie并不需要每次都用到,因此这会造成带宽的部分浪费。
YSlow规则:为静态组件使用不同的域名
因为cookie可以在前后端进行修改,cookie使用不当会被篡改和伪造。
cookie 操作
保存cookie: document.cookie = "name=value; max-age=seconds; domain=domain; path=path"
修改cookie:需要使用相同的name,domain,path,重新设置value和max-age。
删除domain:需要使用相同的name,domain,path,然后指定一个任意的非空value, 设置max-age为0
查找domain:var cookies = document.cookie.split(", ");
session
Session是存储在服务器端的数据
一旦服务器端启用了session,它将约定一个键值作为Session的口令,这个值可以随意约定,比如Tomcat会采用JSESSIONID。一旦服务器检查到用户请求的cookie中没有携带该值,它就会为之生成一个值,这个值是唯一且不可重复的值,并设定超时时间。
每个请求到来时,检查cookie中的口令与服务器端的数据,如果过期,则重新生成session。
在响应中把session的口令写入cookie传给客户端。
setTimeout和setTimeInterval
JavaScript引擎是单线程运行的,无论在什么时候都有且只有一个线程在运行JavaScript程序。
setTimeout或者setTimeInterval的设置的时间参数的具体意思是:在参数指定的时间后将等待执行方法放到执行队列中。如果队列中没有其他方法等待,则会立即执行setTimeout和setTimeInterval指定的方法,因此有时给人好像是立即执行的假象。
如果队列非空,引擎就会从队列头取出一个任务,直到该任务完成,即返回后引擎接着运行下一个任务。在任务没返回前队列中的其他任务是没法被执行的。
如果任务需要的时间非常长,远大于setTimeInterval的定时间隔,那么定时触发线程就会源源不断的产生异步定时事件并放到任务队列尾而不管它们是否已被处理。