继承 枚举 数组
普通模式
弊端:两个对象的原型会指向同一个内存空间,会一起改变。
Father.prototype.lastNmae = 'xyq';
function Father() {
}
function Son() {
}
function inherit(Target, Origin) {
Target.prototype = Origin.prototype;
}
inherit(Son, Father);
var son = new Son();
//可以让son和father有相同的原型,互相之间更改相关联
Father.prototype.lastNmae = 'xyq';
function Father() {
}
function Son() {
}
function inherit(Target, Origin) {
Target.prototype = Origin.prototype;
}
inherit(Son, Father);
Son.prototype.sex = 'male';
var son = new Son();
var father = new Father();
// 结果为son和father都可以访问sex属性为male
圣杯模式:解决互相影响的问题
Father.prototype.lastName = "xyq";
function Father() {}
function Son() {}
function inherit(Target, Origin) {
function F() {}
F.prototype = Origin.prototype;
Target.prototype = new F();
}
inherit(Son, Father);
var son = new Son();
// son和father有相同的原型,但son的更改对于father没有影响
// 此时son的constuctor指向Father()
Father.prototype.lastName = "xyq";
function Father() {}
function Son() {}
function inherit(Target, Origin) {
function F() {}
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constuctor = Target;
//使Target产生的对象的constuctor指向Target()
}
inherit(Son, Father);
var son = new Son();
命名空间:用对象解决变量重名,模块化开发。
属性的表示方法:
obj.属性名
obj.[“属性名”]
遍历枚举
遍历对象的属性:
for( var 变量名 in 对象名){
}
var obj = {
name: '123',
age: 123,
sex: "male",
height: 180,
weight: 75
}
for (var prop in obj) {
console.log(prop);
}
// 可以遍历对象的属性名
在枚举中调用对象属性不能用 对象名.属性名 ,可以用对象名[属性名]
A instanceof B 看 A 对象的原型链上有没有 B 的原型
typeof 可能返回的类型:
- string
- object
- undefined
- function
- number
- boolean
this
- 函数预编译过程 this - > window
- 全局作用域里 this -> window
- call / apply 可以改变函数运行时的 this 指向
- obj.func(); func() 里面的 this 指向 obj
var name = "222";
var a = {
name: "111",
say: function() {
console.log(this.name);
}
}
var fun = a.say;
fun(); //222
a.say(); //111
var b = {
name: "333",
say: function(fun) {
fun();
}
}
b.say(a.say); //222
b.say = a.say;
b.say(); //333
arguments.callee();
可以找到函数的引用名
var num = (function(n) {
if (n == 1) {
return 1;
} else {
return n * arguments.callee(n - 1);
}
}(100));
console.log(num);
//用立即执行函数通过递归求100的阶乘
浅层克隆(引用值不独立,原始值独立)
//克隆函数
function clone(origin,target){
var target = target || {}; //避免用户不传新的对象
for(var prop in origin){
target[prop] = origin[prop];
}
return target;
}
深层克隆(递归)
function deepClone(origin,target){
var target = target || {},
toStr = Object.prototype.toString,
arrStr = "[object Array]";
for(var prop in origin){
if(origin.hasOwnProperty(prop)){
if(origin[prop] !== "null" && typeof(origin[prop] == 'object')){
if(toStr.call(origin[prop] == arrStr)){
target[prop] = origin[prop];
}else{
target[prop] = origin[prop];
}
}
deepClone(origin[prop],target[prop]);
}else{
target[prop] = origin[prop];
}
}
}
数组
定义方式:
数组字面量:var 数组名 = [];
构造方法: var 数组名 = new Array(参数);
参数个数为 1 时代表数组的长度(只能为整数),个数大于 1 时代表数组的具体内容。
数组的所有方法全来自 Array.prototype
数组可以越界读取数据(undefined)
数组的方法:
1. 改变原数组:
- push : 在数组最后面添加内容(可一次添加多个,返回值:数组的新长度
var arr = [];
arr.push(123);
- pop:剪切出数组最后一位,返回值:pop 得到的值
var arr = [1,2];
arr.pop();
//结果为2
- unshift:在数组最前面加内容(可一次添加多个),返回值:新数组的长度
var arr = [1, 2, 3];
arr.unshift(0);
// 数组为:[0,1,2,3]
- shift:剪切数组最前面的内容,返回值:剪切得到的值
var arr = [1, 2, 3];
arr.shift();
// 数组为[2,3]
- reverse:数组逆序,返回值:逆序后的数组
var arr = [1, 2, 3];
arr.reverse();
// 数组为[3,2,1]
- sort:将数组内容排序(按 ASCII 码排序),返回值:排序后的数组
正常使用:
数组名.sort(function (a , b ){
return 变量名;
});
规则:
- 必须写俩形参
- 看返回值:
- 返回值为负数:前一个数放在前面
- 返回值为正数:后一个数放在前面
- 返回值为 0 时:顺序不动
var arr = [4, 2, 3];
arr.sort();
// 数组为[2,3,4]
var arr = [1, 4, 3, 2, 9, 0];
arr.sort().reverse();
// 逆序
// 数组为:[9,4,3,2,1,0]
var arr = [1, 4, 3, 2, 9, 10];
arr.sort();
// 数组为:[1, 10, 2, 3, 4, 9]
var arr = [1, 4, 3, 2, 9, 10];
arr.sort(function(a, b) {
if (a > b) {
return 1;
} else {
return -1;
}
});
// 顺序
// 数组为:[1,2,3,4,9,10]
var arr = [1, 4, 3, 2, 9, 10];
arr.sort(function(a, b) {
if (a < b) {
return 1;
} else {
return -1;
}
});
// 逆序
// 数组为:[10,9,4,3,2,1]
// 升序:
var arr = [1, 4, 3, 2, 9, 10];
arr.sort(function(a, b) {
return a - b;
});
// 降序
var arr = [1, 4, 3, 2, 9, 10];
arr.sort(function(a, b) {
return b - a;
});
- splice:数组切片(可在任意位置添加内容) 返回值:切取下来的数据,组成一个数组
数组名.splice(从第几位开始,截取的长度,在切口处添加新的数据)
var arr = [1, 1, 2, 2, 3, 3, 3];
arr.splice(1, 2);
//数组内容为[1,2,3,3,3
var arr = [1, 1, 2, 2, 3, 3, 3];
arr.splice(1, 2, 0, 0);
//数组内容为:[1, 0, 0, 2, 3, 3, 3
var arr = [1, 2, 3, 5];
arr.splice(3, 0, 4);
//数组内容为:[1,2,3,4,5]
2.不改变原数组:
- concat() :连接两个数组
arr1 = [1, 2, 3, 4];
arr2 = [5, 6, 7, 8];
arr = arr1.concat(arr2);
arr : [1, 2, 3, 4, 5, 6, 7, 8]
- slice : 截取
数组.slice(截取开始位置,截取结束位置)
arr1 = [1, 2, 3, 4];
var arr = arr1.slice(1, 2);
// arr:[2]
arr1 = [1, 2, 3, 4];
var arr = arr1.slice(1);
// arr:[2,3,4]
- join:将数组各位连接起来
数组名.join(字符串);
无参数默认为用 , 连接
arr1 = [1, 2, 3, 4];
var arr = arr1.join("!");
// arr:"1!2!3!4"
- split:将字符串按照某一规则拆分成数组,与 join 互逆
arr1 = [1, 2, 3, 4];
// arr2 = [5, 6, 7, 8];
// var arr = arr1.concat(arr2);
// var arr = arr1.slice(1);
var str = arr1.join("!");
var arr = str.split("!");
// arr: ["1", "2", "3", "4"]
类数组:像数组的对象
属性要为索引(数字)属性,必须有 length 属性,最好加上 push
arguments 是个类数组
var obj = {
"0": 'a',
"1": 'b',
"2": "c",
"length": 3,
"push": Array.prototype.push,
"splice": Array.prototype.splice
}
try{
}catch(e){
}
在 try 里面的发生错误,不会执行错误后的 try 里的代码
在 try 里面中断程序(return),finally 里面的代码仍会执行,会跳过catch的执行
e.name:错误名称
e.message:错误信息
try {
console.log("a");
console.log(b);
console.log("c");
} catch (e) {
console.log('e');
}
console.log("d");
// 输出为:a e d
try {
console.log("a");
console.log(b);
console.log("c");
} catch (e) {
console.log(e.name + ":" + e.message);
}
console.log("d");
可打印出出错信息
(() => {
try {
console.log("try");
return 0;
throw new Error("测试");
} catch (e) {
console.log(e);
} finally {
console.log("finally");
}
})();
// 输出:try finally
Error.name 的六种值对应的信息:
- EvalError : eval()的使用与定义不一致
- RangeError:数值越界
- ReferenceError:非法或不能识别的引用数值
- SyntaxError:发生语法解析错误
- TypeError:操作数类型错误
- URIError:URI 处理函数使用不当
es5.0 严格模式:
不再兼容 es3 的一些不规则语法,使用全新的 es5 规范(不会对不兼容严格模式的浏览器产生影响)
“use strict”;来启动 es5.0 严格模式(写在逻辑最顶端)
可以使用全局严格模式
也可以使用局部函数内严格模式
with(对象名){
代码体;
}
可以将 with 里面的代码的作用域链最顶端改为新给出的对象(降低效率)