js中的继承 枚举和数组介绍

继承 枚举 数组


普通模式

弊端:两个对象的原型会指向同一个内存空间,会一起改变。

1
2
3
4
5
6
7
8
9
10
11
12
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有相同的原型,互相之间更改相关联
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

圣杯模式:解决互相影响的问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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.[“属性名”]

遍历枚举

遍历对象的属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
forvar 变量名 in 对象名){
}
var obj = {
    name'123',
    age123,
    sex"male",
    height180,
    weight75
}
for (var prop in obj) {
    console.log(prop);
}
// 可以遍历对象的属性名

在枚举中调用对象属性不能用 对象名.属性名 ,可以用对象名[属性名]

A instanceof B 看 A 对象的原型链上有没有 B 的原型

typeof 可能返回的类型:

  • string
  • object
  • undefined
  • function
  • number
  • boolean

this

  1. 函数预编译过程 this - > window
  2. 全局作用域里 this -> window
  3. call / apply 可以改变函数运行时的 this 指向
  4. obj.func(); func() 里面的 this 指向 obj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        var name = "222";
        var a = {
            name"111",
            sayfunction({
                console.log(this.name);
            }
        }
        var fun = a.say;
        fun(); //222
        a.say(); //111
        var b = {
            name"333",
            sayfunction(fun{
                fun();
            }
        }
        b.say(a.say); //222
        b.say = a.say;
        b.say(); //333

arguments.callee(); 可以找到函数的引用名

1
2
3
4
5
6
7
8
9
10
11
var num = (function(n{
if (n == 1) {
    return 1;
else {
    return n * arguments.callee(n - 1);
}
}(100));

console.log(num);

//用立即执行函数通过递归求100的阶乘

浅层克隆(引用值不独立,原始值独立)

1
2
3
4
5
6
7
8
//克隆函数
function clone(origin,target){
var target = target || {}; //避免用户不传新的对象
for(var prop in origin){
    target[prop] = origin[prop];
}
return target;
}

深层克隆(递归)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 : 在数组最后面添加内容(可一次添加多个,返回值:数组的新长度
1
2
var arr = [];
arr.push(123);
  • pop:剪切出数组最后一位,返回值:pop 得到的值
1
2
3
4
var arr = [1,2];
arr.pop();

//结果为2
  • unshift:在数组最前面加内容(可一次添加多个),返回值:新数组的长度
1
2
3
4
var arr = [123];
arr.unshift(0);

// 数组为:[0,1,2,3]
  • shift:剪切数组最前面的内容,返回值:剪切得到的值
1
2
3
4
var arr = [123];
arr.shift();

// 数组为[2,3]
  • reverse:数组逆序,返回值:逆序后的数组
1
2
3
4
var arr = [123];
arr.reverse();

// 数组为[3,2,1]
  • sort:将数组内容排序(按 ASCII 码排序),返回值:排序后的数组
正常使用:
1
2
3
数组名.sort(function (a , b ){
return 变量名;
});

规则:

  1. 必须写俩形参
  2. 看返回值:
    1. 返回值为负数:前一个数放在前面
    2. 返回值为正数:后一个数放在前面
    3. 返回值为 0 时:顺序不动
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
var arr = [423];
arr.sort();
// 数组为[2,3,4]

var arr = [143290];
arr.sort().reverse();

// 逆序
// 数组为:[9,4,3,2,1,0]


var arr = [1432910];
arr.sort();

// 数组为:[1, 10, 2, 3, 4, 9]

var arr = [1432910];
arr.sort(function(a, b{
    if (a > b) {
        return 1;
    } else {
        return -1;
    }
});
// 顺序
// 数组为:[1,2,3,4,9,10]

var arr = [1432910];
arr.sort(function(a, b{
    if (a < b) {
        return 1;
    } else {
        return -1;
    }
});

// 逆序
// 数组为:[10,9,4,3,2,1]

// 升序:
var arr = [1432910];
arr.sort(function(a, b{
return a - b;
});
// 降序
var arr = [1432910];
arr.sort(function(a, b{
return b - a;
});
  • splice:数组切片(可在任意位置添加内容) 返回值:切取下来的数据,组成一个数组
    数组名.splice(从第几位开始,截取的长度,在切口处添加新的数据)
1
2
3
4
5
6
7
8
9
10
11
12
var arr = [1122333];
arr.splice(12);
//数组内容为[1,2,3,3,3

var arr = [1122333];
arr.splice(1200);
//数组内容为:[1, 0, 0, 2, 3, 3, 3

var arr = [1235];
arr.splice(304);
//数组内容为:[1,2,3,4,5]

2.不改变原数组:

  • concat() :连接两个数组
1
2
3
4
arr1 = [1234];
arr2 = [5678];
arr = arr1.concat(arr2);
arr : [1, 2, 3, 4, 5, 6, 7, 8]
  • slice : 截取
    数组.slice(截取开始位置,截取结束位置)
1
2
3
4
5
6
7
arr1 = [1234];
var arr = arr1.slice(12);
// arr:[2]

arr1 = [1234];
var arr = arr1.slice(1);
// arr:[2,3,4]
  • join:将数组各位连接起来
    数组名.join(字符串);
    无参数默认为用 , 连接
1
2
3
arr1 = [1234];
var arr = arr1.join("!");
// arr:"1!2!3!4"
  • split:将字符串按照某一规则拆分成数组,与 join 互逆
1
2
3
4
5
6
7
arr1 = [1234];
// 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 是个类数组

1
2
3
4
5
6
7
8
var obj = {
"0"'a',
"1"'b',
"2""c",
"length"3,
"push"Array.prototype.push,
"splice"Array.prototype.splice
}
1
2
3
4
5
try{

}catch(e){

}

在 try 里面的发生错误,不会执行错误后的 try 里的代码
在 try 里面中断程序(return),finally 里面的代码仍会执行,会跳过catch的执行

e.name:错误名称
e.message:错误信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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");
可打印出出错信息
1
2
3
4
5
6
7
8
9
10
11
12
13
(() => {
try {
console.log("try");
return 0;
throw new Error("测试");
} catch (e) {
console.log(e);
} finally {
console.log("finally");
}
})();

// 输出:try finally

Error.name 的六种值对应的信息:

  1. EvalError : eval()的使用与定义不一致
  2. RangeError:数值越界
  3. ReferenceError:非法或不能识别的引用数值
  4. SyntaxError:发生语法解析错误
  5. TypeError:操作数类型错误
  6. URIError:URI 处理函数使用不当

es5.0 严格模式:

不再兼容 es3 的一些不规则语法,使用全新的 es5 规范(不会对不兼容严格模式的浏览器产生影响)

“use strict”;来启动 es5.0 严格模式(写在逻辑最顶端)
可以使用全局严格模式
也可以使用局部函数内严格模式

1
2
3
with(对象名){
代码体;
}

可以将 with 里面的代码的作用域链最顶端改为新给出的对象(降低效率)