Article directory
1. Why write code by hand?
In the daily development process, we often take it out and use it directly, never thinking about the underlying implementation logic of the code, but when I started to study some underlying things, I began to understand the underlying implementation ideas of each method and function in JavaScript , I think this can improve our code level and logical thinking very well.
2. Handwritten code
2.1 Handwritten Object.create() method
2.1.1 Basic use
Definition : A static method that uses an existing object as a prototype to create a new object.
grammar
Object.create(proto[, propertiesObject])
The first parameter proto represents the prototype object of the newly created object.
The second parameter propertiesObject is optional. If not specified as undefined, is the property descriptor of the object's enumerable properties (that is, properties defined by itself, not enumerated properties on its prototype chain) to be added to the newly created object, along with the corresponding property names. These properties correspond to the second parameter of Object.defineProperties().
Return value: the object after adding new properties on the specified prototype object.
Note: If the proto parameter is not null or an object, a TypeError exception is thrown.
2.1.2 Use cases
Create a new object newObj through the Object, create() method and point the prototype object of the new object newObj to the obj object, which is equivalent to newObj. proto == obj and add your own attributes in the second parameter.
//Object.create方法
let obj = {
name: 'zs',
age: 19,
};
let newObj = Object.create(obj, {
hobby: {
// 初始化值
value: true,
// 是否可修改
writable: true,
// 是否能被删除
configurable: true,
// 是否可以用 for in 遍历枚举
enumerable: true,
},
});
console.log(newObj);
console.log(newObj.__proto__ == obj);
The print result output is as follows:
2.1.3 Handwritten implementation
Through the above examples, we know what kind of operations the Object.create() method performs during the calling process.
- Declare a constructor (why declare a constructor here first? Because f.proto == F.prototype)
- Point the prototype object of the constructor to obj (so that the prototype object of the instance object f instantiated by F will naturally point to obj)
- Finally, it can be realized by returning the instance object after instantiation of F.
The specific implementation steps are as follows
Object.myCreate = function (proto, propertiesObject = undefined) {
if (typeof proto !== 'object' && proto !== null && typeof proto !== 'function') {
throw new Error('Uncaught TypeError: Object prototype may only be an Object or null');
}
function F() {
}
F.prototype = proto;
let obj = new F();
if (propertiesObject !== undefined) {
Object.defineProperties(obj, propertiesObject);
}
return obj;
};
test use
let obj = {
name: 'zs',
age: 18,
};
let newObj = Object.myCreate(obj, {
hobby: {
// 初始化值
value: true,
// 是否可修改
writable: true,
// 是否能被删除
configurable: true,
// 是否可以用 for in 遍历枚举
enumerable: true,
},
});
console.log(newObj);
console.log(newObj.__proto__ == obj); // true
2.2 Implement the instanceof method by hand
2.2.1 Basic use
The purpose of instanceof is to determine whether the prototype property of a constructor is on the prototype chain of an instance object. Or to judge that an object is an instance of a constructor.
2.2.2 Use cases
Let's look at a piece of code first, can you think about what will be output?
let str = 'hello';
console.log(str instanceof String);
let str1 = new String('world');
console.log(str1 instanceof String);
The result is 'str' instanceof String, the return value is false, because 'str' is a simple string, it is different
from the string created by the String constructor (new String('str')) ,
The most important thing is to judge whether a constructor is on the prototype chain of an object.
function Person(name, age) {
this.name = name;
this.age = age;
}
let person1 = new Person('zs', 19);
console.log(person1 instanceof Person);
console.log(person1 instanceof Object);
The return results are all true
2.2.3 Handwritten implementation
function myInstanceOf(left, right) {
// 获取对象的的原型
let proto = Object.getPrototypeOf(left);
// 获取构造函数的 prototype 原型对象
let prototype = right.prototype;
while (true) {
// 说明到达了原型链的终点,说明该构造函数不在该原型对象上
if (!proto) return false;
if (proto === prototype) return true;
// 一直沿着原型链向上查找
proto = Object.getPrototypeOf(proto);
}
}
2.3 Implementing the new operator by hand
2.3.1 Basic use
The new operator is used to create an instance object through the constructor
2.3.2 Use cases
Use the new method to create an instance object person1 of the constructor Person
function Person(name, age) {
this.name = name;
this.age = age;
}
let person1 = new Person('zs', 18);
console.log(person1);
2.3.3 Handwritten implementation
Specific display ideas
- An empty object is created;
- Point the empty object __proto__ to the prototype object of the constructor;
- Bind this in the constructor to the newly created object obj and initialize it
4. Make a judgment based on the return type of the constructor. If it is an original value, it will be ignored. If it is an object, it needs to be processed normally
function newObj(Func, ...args) {
// 创建一个空对象
let obj = {
};
// 将空对象的__proto__指向构造函数的原型对象
obj.__proto__ == Func.prototype;
let result = Func.apply(obj, args);
return result instanceof Object ? result : obj;
}
console.log(newObj(Person, 'zs', 30));
Test the newObj method implemented by hand
let person2 = newObj(Person, 'zs', 19);
console.log(person2);
successfully achieved