- 手写
instanceof
function myInstanceof(left, right) {
// 这里先用typeof来判断基础数据类型,如果是,直接返回false
if(typeof left !== 'object' || left === null) return false;
// getProtypeOf是Object对象自带的API,能够拿到参数的原型对象
let proto = Object.getPrototypeOf(left);
while(true) { //循环往下寻找,直到找到相同的原型对象
if(proto === null) return false;
if(proto === right.prototype) return true;//找到相同原型对象,返回true
proto = Object.getPrototypeof(proto);
}
}
// 验证一下自己实现的myInstanceof是否OK
console.log(myInstanceof(new Number(123), Number)); // true
console.log(myInstanceof(123, Number)); // false
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
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
- 通用的数据类型判断方法
function getType(obj){
let type = typeof obj;
if (type !== "object") { // 先进行typeof判断,如果是基础数据类型,直接返回
return type;
}
// 对于typeof返回结果是object的,再进行如下的判断,正则返回结果
return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1'); // 注意正则中间有个空格
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- new的实现
function _new(func, ...args) {
if(typeof func !== 'function') {
throw 'func must be a function';
}
let obj = new Object();
obj.__proto__ = Object.create(func.prototype);
let res = func.apply(obj, [...args]);
let isObject = typeof res === 'object' && typeof res !== null;
let isFunction = typeof res === 'function';
return isObject || isFunction ? res : obj;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- call的实现
Function.prototype.call = function (context, ...args) {
var context = context || window;
context.fn = this;
var result = eval('context.fn(...args)');
delete context.fn
return result;
}
1
2
3
4
5
6
7
2
3
4
5
6
7
- apply的实现
Function.prototype.apply = function (context, args) {
let contexts;
contexts=context || window;
contexts.fn = this;
let result = eval('contexts.fn(...args)');
delete contexts.fn
return result;
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- bind的实现
Function.prototype.bind = function (context, ...args) {
if (typeof this !== "function") {
throw new Error("this must be a function");
}
var self = this;
var fbound = function () {
self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments)));
}
if(this.prototype) {
fbound.prototype = Object.create(this.prototype);
}
return fbound;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- 深拷贝的实现
// 判断是不是复杂类型,其实就是判断数据类型是不是object,但有两个例外要考虑,一个例外是null要排除,一个例外是function要包含。
const isComplexDataType = (obj) => (typeof obj === "object" || typeof obj === "function") && obj !== null;
// 深拷贝的核心方法
const deepClone = function (obj, hash = new WeakMap()) {
// 日期对象直接返回一个新的日期对象
if (obj.constructor === Date) return new Date(obj);
// 正则对象直接返回一个新的正则对象
if (obj.constructor === RegExp) return new RegExp(obj);
// 如果循环引用了就用 weakMap 来解决
if (hash.has(obj)) return hash.get(obj);
// getOwnPropertyDescriptors方法返回指定对象上一个自有属性对应的属性描述符
let allDesc = Object.getOwnPropertyDescriptors(obj);
//遍历传入参数所有键的特性,Object.create方法创建一个新对象,使用现有的对象来提供新创建对的__proto__
let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc);
//继承原型链
hash.set(obj, cloneObj);
for (let key of Reflect.ownKeys(obj)) {
cloneObj[key] =
isComplexDataType(obj[key]) && typeof obj[key] !== "function"
? deepClone(obj[key], hash)
: obj[key];
}
return cloneObj;
};
// 下面是验证代码
let obj = {
num: 0,
str: "",
boolean: true,
unf: undefined,
nul: null,
obj: { name: "我是一个对象", id: 1 },
arr: [0, 1, 2],
func: function () {
console.log("我是一个函数");
},
date: new Date(0),
reg: new RegExp("/我是一个正则/ig"),
[Symbol("1")]: 1,
};
Object.defineProperty(obj, "innumerable", {
enumerable: false,
value: "不可枚举属性",
});
obj = Object.create(obj, Object.getOwnPropertyDescriptors(obj));
obj.loop = obj; // 设置loop成循环引用的属性
let cloneObj = deepClone(obj);
cloneObj.arr.push(4);
console.log("obj", obj);
console.log("cloneObj", cloneObj);
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
- 继承的实现
# 盗用构造函数
function SuperType() {
this.colors = ["red", "blue", "green"];
}
function SubType() {
// 继承 SuperType
SuperType.call(this);
}
let instance1 = new SubType();
instance1.colors.push("black");
console.log(instance1.colors); // "red,blue,green,black"
let instance2 = new SubType();
console.log(instance2.colors); // "red,blue,green"
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 原型
function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function () {
return this.property;
};
function SubType() {
this.subproperty = false;
}
// 继承 SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function () {
return this.subproperty;
};
let instance = new SubType();
console.log(instance.getSuperValue());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 组合继承
function SuperType(name) {
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function () {
console.log(this.name);
};
function SubType(name, age) {
// 继承属性
SuperType.call(this, name);
this.age = age;
}
// 继承方法
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function () {
console.log(this.age);
};
let instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
console.log(instance1.colors); // "red,blue,green,black"
instance1.sayName(); // "Nicholas";
instance1.sayAge(); // 29
let instance2 = new SubType("Greg", 27);
console.log(instance2.colors); // "red,blue,green"
instance2.sayName(); // "Greg";
instance2.sayAge(); // 27
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
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
← 函数声明和表达式 JS | 迭代器和生成器 →