第二讲
类和对象
类可以看成一个工厂,我规定了这个工厂里要生产的东西,其实就是生成的对象,东西的大小,样式等,就相当于对象的属性,我们定义好一个类后,生成的对象就有了那些属性。
但是,在JS里没有类这个东西,就是说我们没有一个明确的语法来声明一个类,但是我们可以通过JS其他的方法达到这个目的,这个知识内容较复杂,我们不讲,想在前端继续走下去的以后需要私下里去看,JS里是有对象这个概念的,就是我们下面要讲的内容
JS里的对象是引用类型
这几个类型是JS已经封装好的,大家可以把他们看成是类
var a = {};
b = a;
b.name = "SIPC";
console.log(a.name); // SIPC
Object类型
// 字面量声明法 (推荐)
var organization = {
name: "SIPC",
age: 6
}
// new操作符
var organization = new Object();
organization.name = "SIPC";
organization.age = 6;
对象属性的操作
// 声明属性
var person = {};
person.name = "jorten";
person.age = 19;
// 访问属性
console.log(person.name); //点表示
console.log(person["name"]); //方括号表示
//特殊形式的需要用方括号表示
person["first name"] = "xia";
//JS中字符串可以用""表示也可以用''表示
// 删除属性
delete person['name'];
像我们刚才说的,一个类要定义生成对象的一些属性,那怎么保存这些属性呢?就是用prototype
Object.prototype.age = 20;
var person = {};
console.log(person.age); //20
所有对象是的Object的子类
子类就是说它生成的对象有了父类的属性和方法,所以我们生成的对象不用定义属性就有刚才提到的属性和方法
var a = new Object();
console.log(a.toString());
// [object Object]
判断一个对象的类型
var arr = new Array();
console.log(Object.prototype.toString.call(arr));
// [object Array]
console.log(typeof arr);
// object
console.log(arr instanceof Array);
// true
console.log(arr instanceof Object);
// true
var reg = new RegExp();
console.log(Object.prototype.toString.call(reg));
// [object RegExp]
声明数组 :
// 字面量(推荐)
var arr1 = [1, 2, 3]
// new方法
var arr2 = new Array();
var arr3 = new Array("Jorten");
var arr4 = new Array(1, 2, 3);
var arr5 = new Array(20);
操作数组 :
var arr = [1, 2, 3];
console.log(arr[0])
// 1
arr[3] = 4;
console.log(arr);
// [1, 2, 3, 4]
conosole.log(arr[10])
// undefined
var arr = [];
arr[0] = undefined;
arr[1] = 1;
arr[2] = new Object();
arr[3] = [1, 2, 3];
arr[4] = "sipc"
console.log(arr);
// undefined, 1, Object, Array(3), "sipc"
使用分隔符来构造字符串
var arr = ['red', 'green', 'blue'];
console.log(arr.join(', ');
// red, green, blue
console.log(arr.join('|');
// red|green|blue
console.log(arr.join('');
// redgreenblue
console.log(arr.join(undefined));
// red,green,blue
console.log(arr.join());
// red,green,blue
//如果不传值或传入undefined 默认使用逗号作为分隔符
表明一个数组的长度
var arr = [1, 2, 3]
console.log(arr.length);
// 3
可以通过修改length来改变数组
var arr = [1, 2, 3, 4]
arr.length = 3;
console.log(arr);
// [1, 2, 3]
console.log(arr[3]);
// undefined
var arr = [];
arr.length = 2;
console.log(arr);
// [undefined, undefined] 未赋值的项全为undefined
var arr1 = [1, 2, 3];
arr1[99] = 100;
console.log(arr1.length);
// 100 未赋值的项全为undefined
push:在数组的结尾加上一个元素
var arr = [1, 2];
arr.push(3);
console.log(arr);
// [1, 2, 3]
pop:删去数组的结尾元素
var arr = [1, 2, 3];
arr.pop();
console.log(arr);
// [1, 2]
shift:删去数组的第一个元素
unshift:在开头添加一个元素
var arr = [1, 2];
arr.shift();
console.log(arr);
// [2]
var arr = [1, 2];
arr.unshift(0);
console.log(arr);
// [0, 1, 2]
reverse:将数组倒序
var arr = [1, 2, 3];
arr.reverse();
console.log(arr);
// [3, 2, 1]
sort:将数组升序排列
var arr = [2, 3, 1, 5, 4];
arr.sort();
console.log(arr);
// [1, 2, 3, 4, 5]
// 注意
var arr = [2, 4, 10, 14];
arr.sort();
console.log(arr);
// [10, 14, 2, 4]
// 说好的升序排列呢?
默认的sort方法是比较字符串的大小的,而在字符串的大小比较中"14" < "2", 因为字符串的比较会先从他们的第一个字符开始比较他们的Unicode码,咱们这里可以看作数字的ASCII码,因为1的ASCII码小于2,所以"14" < "2",
如果第一个字符相同,就一直往下比较,如果全相等就相等
console.log(14 < 2);
// false
console.log("14" < "2");
// true
console.log("1" < "11");
// true
那么如何让sort真正的升序排列?
sort里可以传入一个比较函数作为参数
比较函数里有两个参数
返回负数第一个参数在第二个参数之前
返回0两个参数相等
返回正数第一个参数在第二个参数之后
我们传入比较函数后就可以让数组的每一项进行两两比较了
var arr = [2, 11, 14, 4, 1];
arr.sort(function(val1, val2) {
if(val1 < val2) {
return -1;
} else if(val1 === val2) {
return 0;
} else {
return 1;
}
});
console.log(arr);
// [1, 2, 4, 11, 14]
// 更简单的写法
arr.sort(function(val1, val2) {
return val1 - val2;
});
console.log(arr);
// [1, 2, 4, 11, 14]
拼接数组,传入一个或多个数组作为参数,如果不是数组则直接添加,注意和前面不同的是原数组不变,返回值为拼接的数组
var arr1 = [1, 2, 3];
var arr2 = arr1.concat(4, [5, 6]);
console.log(arr1);
// [1, 2, 3]
console.log(arr2);
//[1, 2, 3, 4, 5, 6]
对数组进行切割,截取原数组的一部分
var arr = [1, 2, 3, 4];
var arr2 = arr.slice();
console.log(arr);
// [1, 2, 3, 4]
console.log(arr2);
// [1, 2, 3, 4]
arr2 = arr.slice(1);
console.log(arr2);
// [2, 3, 4]
arr2 = arr.slice(1, 3);
console.log(arr2);
// [2, 3]
var arr1 = [1, 2, 3, 4];
arr1.splice(1, 1);
console.log(arr1);
// [1, 3, 4]
arr1.splice(1, 0, 1.5);
console.log(arr1);
// [1, 1.5, 3, 4]
arr1.splice(2, 1, 2);
console.log(arr1);
// [1, 1.5, 2, 4]
arr1.splice(1, 0, 7, 9);
console.log(arr1);
// [1, 7, 9, 1.5, 2, 4]
返回目标的索引值
var arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
console.log(arr.indexOf(2));
// 1
console.log(arr.indexOf(2, 2));
// 7
console.log(arr.indexOf(123));
// -1
console.log(arr.lastIndexOf(2));
// 7
console.log(arr.lastIndexOf(2, 4));
// 1
迭代
传入一个函数作为参数
函数有三个参数:数组项的值,改项在数组中的位置,数组对象本身
归并方法
迭代所有项返回最终值
传入一个函数和一个基础值
函数有4个参数,为前一个值,当前值,项的索引,数组对象
var values = [1, 2, 3, 4, 5];
var sum = values.reduce(function(prev, cur, index, array) {
return prev + cur;
}, 10);
console.log(sum);
// 25
// 第二个参数没有则以0开始
类数组
有着和数组一样的元素分布,可以像操作数组一样操作他们,也有length属性,但是没有数组的其他方法,如push等
上节课讲的arguments以及以后要讲的HTMLDOM数组就是这样的类数组
类数组转化为数组的方法:
var arr1 = [].slice.call(arr);
声明一个日期对象
var now = new Date()
now = new Date("March 20, 2016")
now = new Date(1231535161);
Date.parse(now)
返回此时间到1970年1月1日零点的毫秒数
Date.now()
返回现在到1970年1月1日零点的毫秒数
Date.UTC(2016, 2, 20,17, 55, 55)
返回2016年3月20日17:55:55到1970年1月1日零点的毫秒数
var pattern = /at/g;
var pattern = new RegExp("at", "g");
g:全局模式
i:不区分大小写
m:多行模式
用来匹配字符串
var text = "mom and dad and son";
var pattern = /[a-z]d/gi;
var matches = pattern.exec(text);
console.log(matches);
// ["nd", index: 5, input: "mom and dad and son"]
matches = pattern.exec(text);
console.log(matches);
// ["ad", index: 9, input: "mom and dad and son"]
index代表索引的位置,input代表匹配的字符串
function sayName(obj) {
console.log(obj.name);
}
// 匿名函数
var sayColor = function(obj) {
console.log(obj.color);
}
// 不推荐
var sayAge = new Function("obj", "console.log(obj.age)");
函数表达式
// 函数声明完立即调用可以吗?
function sayHi() {
console.log("Hi");
}();
// 会报错,因为浏览器会把它当成函数声明 是不能执行的
(function sayHi() {
console.log("Hi");
})();
// 可以,因为这是函数表达式 可以执行
this指的是函数执行的环境对象
var a = {
color: 'red'
}
var color = 'yellow';
function sayColor() {
console.log(this.color);
}
sayColor();
// yellow
// 因为在全局作用域上调用的函数,所以this指向的是全局对象window
var a = {
color: 'red'
}
var color = 'yellow';
function sayColor() {
console.log(this.color);
}
sayColor.call(a);
// red
// this指向了a对象
改变this的指向,在特定作用域调用函数
不同之处为函数参数传入的形式
创建一个函数的实例,其this值绑定到传给bind()函数的值
var a = {
color: 'red'
}
var color = 'yellow';
function sayColor() {
console.log(this.color);
}
var sayColorA = sayColor.bind(a);
sayColorA();
// red
arguments有一个callee属性:指向拥有这个arguments的函数
函数的caller属性:保存着调用当前函数的函数的引用
function inner() {
console.log(arguments.callee.caller);
}
function outer() {
inner();
}
outer();
Boolean()
Number()
将目标转成布尔值/数字
num.toString([2, 8, 10, 16])
num.toFixed(2)
console.log(Boolean(2));
// true
console.log(Number([1, 2]));
// NaN
console.log(1.004.toFixed(2));
// 1.00
字符串可以索引
var str = "hello world";
console.log(str[0]);
// h
str[1] = "a";
console.log(str);
// hallo world
JS中的字符串可以用""也可以用''表示,
但是要统一
charAt:返回第i个字符
charCodeAt:返回第i个字符的Unicode码
var str = "Hello World";
console.log(str.charAt(0));
// H
console.log(str.charCodeAt(3));
// 108
var str1 = "hello";
var str2 = str1.concat(" ", "world", "!");
console.log(str2);
// hello world!
console.log(str2.slice(6));
// world!
和数组一样,拼接和切割
和数组一样索引
var str = "hello world";
console.log(str.indexOf("llo"));
// 2
console.log(str.indexOf("o"));
// 4
console.log(str.lastIndexOf("o"));
// 7
删除字符串开头和结尾的字符串
var str = " hello world ";
var str1 = str.trim();
console.log(str1);
// hello world
将字符串变为大写/小写
var str = "Hello World";
console.log(str.toUpperCase());
// HELLO WORLD
console.log(str.toLowerCase());
// hello world
匹配字符串
var text = "cat, bat, sat, fat";
var pattern = /at/;
console.log(text.match(pattern));
// ["at", index: 1, input: "cat, bat, sat, fat"]
按照所传参数分割字符串成数组
var str = "1, 2, 3, 4, 5";
console.log(str.split(", "));
// ["1", "2", "3", "4", "5"]
console.log(str.split(""));
// ["1", ",", " ", "2", ",", " ", "3", ",", " ", "4", ",", " ", "5"]
console.log(str.split());
// ["1, 2, 3, 4, 5"]
eval("alert('hello')");