参考自

对象及函数

对象

创建对象

对象直接使用键值对的方式进行定义

var xiaoming = {
name: '小明',
birth: 1990,
school: 'No.1 Middle School',
height: 1.70,
weight: 65,
score: null
age: function () {
var y = new Date().getFullYear();
return y - this.birth;
}
'middle-school': 'No.1 Middle School'
};
xiaoming['middle-school']; // 'No.1 Middle School'
xiaoming.age();


如果键时字符串的话必须使用[]的方式进行访问,例如middle-school

如果想判断某个属性是否在这个类中可以使用in。例如:'name' in xiaoming,返回为true。

但是这种方法对继承而来的属性也会判断为真。例如:'toString' in xiaoming; // true.这个时候就需要使用hasOwnProperty()方法。例如:xiaoming.hasOwnProperty('name'); // true

另一种创建方法是:

function Student(name) {
this.name = name;
this.hello = function () {
alert('Hello, ' + this.name + '!');
}
}
var xiaoming = new Student('小明');
var xiaohong = new Student('小红');
xiaoming.constructor === Student.prototype.constructor;

这种方式的好处是可以重复创建

java对每个创建的对象都会设置一个原型,指向原型对象。原型对象有一个constructor属性指向函数,而函数有一个prototype指向原型。因此为了节省空间,可以把一些共用的函数或变量移动到原型变量上就可以了
function Student(name) {
this.name = name;
}

Student.prototype.hello = function () {
alert('Hello, ' + this.name + '!');
};

这样所有对象本身都没有hello函数,但是他们可以调用这个函数。

当然有更简洁的方式

class Student {
constructor(name) {
this.name = name;
}

hello() {
alert('Hello, ' + this.name + '!');
}
}

class关键字自ES6被引入,并且可以在后面使用extends关键字继承某个类

标准对象

有一些对象js已经帮我们设定好了。

Date()

var now = new Date();
now; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
now.getFullYear(); // 2015, 年份
now.getMonth(); // 5, 月份,注意月份范围是0~11,5表示六月
now.getDate(); // 24, 表示24号
now.getDay(); // 3, 表示星期三
now.getHours(); // 19, 24小时制
now.getMinutes(); // 49, 分钟
now.getSeconds(); // 22, 秒
now.getMilliseconds(); // 875, 毫秒数
now.getTime(); // 1435146562875, 以number形式表示的时间戳

Date中的月份是从0开始的,也就是说0表示1月份

RegExp

一些基础知识

  • \s: 表示空格
  • \d: 表示数字
  • \w: 表示一个字母或数字

正则表达式创建:

  • 通过/ ... /: 如果在/后加g表示全局匹配,每次匹配完后会返回值,然后从上次匹配的位置往后匹配 例如: var re1 = /ABC-001/;
  • 通过new RegExp(‘正则表达式’, 其他参数): 第二个参数可以是’g’表示全局匹配

可以使用test(‘匹配字符串’)进行匹配

var re = /^\d{3}\-\d{3,8}$/;
re.test('010-12345'); // true
re.test('010-1234x'); // false
re.test('010 12345'); // false

var s = 'JavaScript, VBScript, JScript and ECMAScript';
var re=/[a-zA-Z]+Script/g;

// 使用全局匹配:
re.exec(s); // ['JavaScript']
re.lastIndex; // 10

re.exec(s); // ['VBScript']
re.lastIndex; // 20

re.exec(s); // ['JScript']
re.lastIndex; // 29

re.exec(s); // ['ECMAScript']
re.lastIndex; // 44

re.exec(s); // null,直到结束仍没有匹配到

应用:

切分字符串

例如:
a b c'.split(/\s+/); // ['a', 'b', 'c']。split的参数可以使用正则表达式

浏览器对象

window

window有innerHeight和innerWeight属性,用来获取内部的宽度和高度,也就是网页可以使用的大小。

还有outerHeight和outerWeight属性,指的是浏览器所使用的大小(浏览器还有一些工具栏会占用一定的空间)

navigator

一些浏览器的信息,但是这些信息可以被用户更改

  • navigator.appName:浏览器名称;
  • navigator.appVersion:浏览器版本;
  • navigator.language:浏览器设置的语言;
  • navigator.platform:操作系统类型;
  • navigator.userAgent:浏览器设定的User-Agent字符串。

screen

指的是屏幕的信息(这是计算机本身的信息)

  • screen.weight:
  • screen.height:
  • screen.colorDepth: 返回颜色位数。如8位,16位,24位

location

location表示当前页面的URL。例如location.href

如果想获取各个部分的信息,可以使用

  • location.protocol; // ‘http’
  • location.host; // ‘www.example.com’
  • location.port; // ‘8080’
  • location.pathname; // ‘/path/index.html’
  • location.search; // ‘?a=1&b=2’
  • location.hash; // ‘TOP’
  • location.reload(): 重新加载当前页面
  • location.assign(URL): 加载一个新页面

document

document表示当前DOM树的根节点

  • getElementById(): 根据Id获得节点
  • getElementByName(): 根据标签名获得节点
  • cookie: 当前页面的cookie。但是如果浏览器使用了httponly选项就无法获取
  • createElement(): 创建便签,如h1等
  • createTextNode(): 创建文本节点
  • node.appendChild(): 为这个节点添加子节点
  • element.insertBefore(new, ref): 将new节点插入到ref之前
  • element.innerHTML: 这个标签下所有内容
  • element.style: 返回这个元素的css
  • element.style.left
  • element.setAttribute()
  • element.getAttribute()
  • element.addEventListener()
  • element.value: 获得表单输入的值
  • element.check: 单选框或复选框是否被选上
  • element.submit(): 提交表单。但是这种方法会干扰本身的提交。另一种方式是在触发onsubmit时修改
<!-- HTML -->
<form id="test-form" onsubmit="return checkForm()">
<input type="text" name="test">
<button type="submit">Submit</button>
</form>

<script>
function checkForm() {
var form = document.getElementById('test-form');
// 可以在此修改form的input...
// 继续下一步:
return true;
}
</script>

File

在新版的js中,提供了File和FileReader来读取对象。

可以通过获取上传文件控件并通过fileinput.files[0]来获得文件对象,然后通过file.name,file.size等可以获得文件的信息

FileReader可以用来读取文件。file_reader.readAsDataURL(file);用来读取文件。reader.onload = function(e) {…}将在文件读取完成之后自动调用

var
fileInput = document.getElementById('test-image-file'),
info = document.getElementById('test-file-info'),
preview = document.getElementById('test-image-preview');
// 监听change事件:
fileInput.addEventListener('change', function () {
// 清除背景图片:
preview.style.backgroundImage = '';
// 检查文件是否选择:
if (!fileInput.value) {
info.innerHTML = '没有选择文件';
return;
}
// 获取File引用:
var file = fileInput.files[0];
// 获取File信息:
info.innerHTML = '文件: ' + file.name + '<br>' +
'大小: ' + file.size + '<br>' +
'修改: ' + file.lastModifiedDate;
if (file.type !== 'image/jpeg' && file.type !== 'image/png' && file.type !== 'image/gif') {
alert('不是有效的图片文件!');
return;
}
// 读取文件:
var reader = new FileReader();
reader.onload = function(e) {
var
data = e.target.result; // 'data:image/jpeg;base64,/9j/4AAQSk...(base64编码)...'
preview.style.backgroundImage = 'url(' + data + ')';
};
// 以DataURL的形式读取文件:
reader.readAsDataURL(file);
});

AJAX

如果没有js,那么浏览器一旦提交表单就会开始刷新页面,然后在新页面告诉是成功还是失败。浏览器运作的方式就是一个HTTP请求对应一个页面

我们可以通过JS发送这个请求,然后用JS接收页面来决定是否更新,这样就可以在一个页面中不断的发送数据了。

function success(text) {
var textarea = document.getElementById('test-ie-response-text');
textarea.value = text;
}

function fail(code) {
var textarea = document.getElementById('test-ie-response-text');
textarea.value = 'Error code: ' + code;
}

var request = new ActiveXObject('Microsoft.XMLHTTP'); // 新建Microsoft.XMLHTTP对象

request.onreadystatechange = function () { // 状态发生变化时,函数被回调
if (request.readyState === 4) { // 成功完成
// 判断响应结果:
if (request.status === 200) {
// 成功,通过responseText拿到响应的文本:
return success(request.responseText);
} else {
// 失败,根据响应码判断失败原因:
return fail(request.status);
}
} else {
// HTTP请求还在继续...
}
}

// 发送请求:
request.open('GET', '/api/categories');
request.send();

alert('请求已发送,请等待响应...');

首先需要创建一个XMLHttpRequest对象,然后设置onreadystatechange的回调函数,返回4请求成功,200代表返回成功,否则是返回不成功。

  • open(type, url): 第一个参数指明是GET还是POST,第二个参数指明请求的URL
  • send(FormData): 如果是GET则不需要参数,如果是POST则需要传递字符串或者是formdata

但是url只能是本域的,也就是说域名要相同(甚至前面加了www也是不同的域名),请求的页面是相同的http协议(http或https),端口号也要相同。

那么怎么请求外域的页面呢?

  1. 在相同域名下架设代理服务器进行转发
  2. 通过JSONP,但是他只能处理GET请求

例如:

<html>
<head>
<script src="http://example.com/abc.js"></script>
...
</head>
<body>
...
</body>
</html>

然后返回值是一个函数调用,例如返回foo(‘data’),这时我们只需要在本地准备好foo函数就会自动调用了。

函数

定义函数: function function_name(var a, var b, ...){ return ...;}

这里和一般编程语言不同的是它没有定义返回值类型,因为js是弱类型语言,所有类型都使用var表示,所以就不需要特别写返回值了。

函数的参数实际上是不确定的,可以没有也可以由很多,例如上面如果少于两个参数就可以直接使用a,b来获得,如果多于两个则需要使用argument[i]进行调用。argument.length表示了参数的个数

闭包

这里的返回值可以是一个函数(类似于c++中的函数指针),并且函数也可以没有名字(就是下面arr.reduce内的内容)。例如:

function lazy_sum(arr) {
var sum = function () {
return arr.reduce(function (x, y) {
return x + y;
});
}
return sum;
}
var f = lazy_sum(arr);
f();

但是仍有一些区别,这里的f不是立刻执行的,也就是说lazy_sum这个函数并没有真正结束,因此里面的参数也不会重置,例如:

function count() {
var arr = [];
for (var i=1; i<=3; i++) {
arr.push(function () {
return i * i;
});
}
return arr;
}

var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];
f1();//ans = 16
f2(); // ans = 16
f3(); // ans = 16

generator

例如:

function* foo(x) {
yield x + 1;
yield x + 2;
return x + 3;
}

for(var i of foo(0))
{
console.log(i);
}
输出:
1
2
3

yield用来表示返回,因此这个函数相当于返回了多次。注意这种函数还需要加一个*号。

最后可以不写return,系统会自动添加return undefined

对象中的函数

在对象中的函数要复杂一些。例如:

var xiaoming = {
name: '小明',
birth: 1990,
age: function () {
var y = new Date().getFullYear();
return y - this.birth;
}
};
xiaoming.age();

这里有一个麻烦的变量this,this始终指向当前对象,但是问题是它的当前对象范围比较窄

var xiaoming = {
name: '小明',
birth: 1990,
age: function () {
function getAgeFromBirth() {
var y = new Date().getFullYear();
return y - this.birth;
}
return getAgeFromBirth();
}
};

上面这种方式就会出现问题,因为getAgeFromBirth的上一级是一个函数,因此this变成Undefined了。

一种解决方法是使用apply函数,apply函数可以指定使用的对象,例如:

function getAge() {
var y = new Date().getFullYear();
return y - this.birth;
}

var xiaoming = {
name: '小明',
birth: 1990,
age: getAge
};

xiaoming.age(); // 25
getAge.apply(xiaoming, []); // 25, this指向xiaoming, 参数为空

  • apply(对象,参数): 第一个参数时对象名称,第二个参数时这个函数所使用的方法