1. instansof 方法
instanceof 功能介绍
**功能1:**instanceof用于判断一个变量是否某个对象的实例。
更深层次的是:a instanceof Foo ,instanceof 操作符的左操作符是一个普通的对象,右操作数是一个函数。 instanceof回答的问题是: 在a的整条[[Prototype]]链中是否有Foo.prototype指向的对象。
如var a=new Array(); console.log(a instanceof Array);会输出true,
同时console.log(a instanceof Object)也会输出true;这是因为Array是object的子类。
再如:function test(){}; var a=new test(); console.log(a instanceof test)会输出true。
功能2: instanceof 判断数据类型 ,其实就是判断在a的整条[[Prototype]]链中是否有Foo.prototype指向的对象。
如:let str = new String( '麻烦各位点点赞');
str instanceof String // true
instanceof 底层实现
1. instanceof 最终实现代码如下:
**第一种:
**
function instance_of(L,R) {
var O = R.prototype; // 构造函数的原型对象
L = L.__proto__;
while(true){
if(L === null) return false;
if(L === O){
return true
}
L = L.__proto__;
}
}
第二种:
function myInstanceof(L, R) {
// 这里先用typeof来判断基础数据类型,如果是,直接返回false
if(typeof L !== 'object' || L === null) return false;
// getProtypeOf是Object对象自带的API,能够拿到参数的原型对象
let proto = Object.getPrototypeOf(L);
while(true) { //循环往下寻找,直到找到相同的原型对象
if(proto === null) return false;
if(proto === R.prototype) return true;//找到相同原型对象,返回true
proto = Object.getPrototypeof(proto);
}
}
2. 上述代码实现的历程:
由于instenceof使用了原型方面的知识,所以直接上一个经典原型学习图。
- 每一个实例(例如 f1 和 f2)都有一个"__proto__"指向Foo.prototype。
- 评判依据: 面对
function test(){}; var a=new test();当a.__proto__ === text.prototype,则f1 instanceof test 就会返回true。
初级instanceof 的实现代码为:
function instance_of(L,R) {
var O = R.prototype; // 构造函数的原型对象
if(L.__proto__ === O){
return true;
}
else{
return false;
}
}
不足:
instanceof 要搞定的是:在a的整条[[Prototype]]链中是否有Foo.prototype指向的对象。
而面对于a instanceof Object就没法子的返回true了,所以根据经典图,知道一直有"__proto__"属性指到null,所以弄个循环就可以搞定了。
while(true){
if(L === null)
return false;
if(L === O){
return true
}
L = L.__proto__;
}
当L = L.__proto__为null时循环会退出。
由于instanceof判断数据类型有弊端:
实现一个全局通用的数据类型判断方法,代码如下:
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');
// 注意正则中间有个空格
}
2.Object.create 方法
Object.create 功能介绍
- 语法:
Object.create(proto, [propertiesObject])
//方法创建一个新对象,使用现有的对象来提供新创建的对象的proto。 - 参数:
- proto : 必须。表示新建对象的原型对象,即该参数会被赋值到目标对象(即新对象,或说是最后返回的对象)的原型上。该参数可以是
null,对象, 函数的prototype属性(创建空的对象时需传null , 否则会抛出TypeError异常)。 - propertiesObject : 可选。
- 返回值:在指定原型对象上添加新属性后的对象。
const me = Object_create(person);代码意思为:调用Object.create()会凭空创建一个"新"对象并把新对象内部的[[Prototype]]关联到你的指定对象(即为"person");
Object.create 底层实现
**1. 代码实现依据:**调用Object.create()会凭空创建一个"新"对象并把新对象内部的[[Prototype]]关联到你的指定对象。
实现代码如下:
function Object_create(proto) {
function F() {}
F.prototype = proto;
return new F();
}
验证代码:
const person = {
isHuman: false,
printIntroduction: function() {
console.log('My name is ${this.name} .Am I human ? ${this.isHuman}');
}
}
const me = Object_create(person);
console.log(me.isHuman);
console.log(me.__proto__);
console.log(me.__proto__ === person);
终端打印:
2. 上述验证代码实现的历程:
创建一个新的构造函数F(),让F.prototype指向proto。
由const me = Object_create(person); 得到me.__peoto__ ===person。
me.__peoto__ === (Me.prototype) === person。实现了继承。
3 Funtion.prototype.call 方法
Funtion.prototype.call功能介绍
**call()** 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
1.使用 call 方法调用函数并且指定上下文的 'this'
例如: foo.call.(obj),可以在调用foo时强制把foo.this绑定到obj。
2.使用 call 方法调用父构造函数,
function Aniaml(name) {
this.name = name;
}
function Cat(name, price) {
Product.call(this, name);
this.food = 'fish';
}
语法: function.call(thisArg, arg1, arg2, ...)
Funtion.prototype.call 底层实现:
1. 代码实现如下:
Function.prototype.Mycall = function (obj, ...rest) {
var obj = obj || window;
obj._fn = this;
var res = eval('obj._fn(...rest)');
delete obj._fn
return res;
}
2. 上述代码实现的历程:
如果要了解Funtion.prototype.call的底层机制,得了解词法作用域。欢迎观看大佬的juejin.cn/post/692423…
明白call实现的真正的东西:foo.call.(obj),可以在调用foo时强制把foo.this绑定到obj。
1.来看这一段代码
var a = 1;
function test() {
console.log(this === window);
console.log(this.a);
}
test();
输出为:
说明: this已经绑定了全局对象
2.来看这一坨代码
var testObj = {
a:3,
test: function() {
console.log(this === testObj,'判断');
console.log(this.a);
}
}
testObj.test();
输出为:
说明:this已经绑定了testObj
3.来看这一堆代码
function test() {
console.log(this === obj);
console.log(this.a,'obj');
}
var obj = {
a:2
}
test.call(obj);
输出为:
**说明:**this已经绑定了obj
对于1, 2 ,3的代码进行总结:
- 函数作为 普通函数调用的时候 this === window
- 函数作为 对象的属性 调用的时候 this === 对象的属性
- 函数用 call 来调用 this === call 第一个参数
4. 由于是通过"."进行调用call,所以使用Foo.prototype.Mycall进行扩展。
Function.prototype.myCall = function () {
console.log("欢迎来到Mycall的世界!")
}
function testMycall() { }
testMycall.myCall();
所有借用"函数作为 对象的属性 调用的时候 this === 对象的属性",来实现.call。
代码如下:
function testMycall() {
console.log(this.b);
}
var testObj1 = {
b: 'b val',
_fn:testMycall
}
testObj1._fn(); // this === testObj1
在testObj1中定义一个_fn:testMycall,然后调用testObj1.fn(),实现了this绑定到了testObj1。
实现了类似testMycall.call(testObj1)的功能。
所以:testObj1._fn = testMycall,要获取"testMycall",就用"this"(this === testMycall)
Funtion.prototype.call实现代码版本1:
Function.prototype.myCall = function (obj) {
obj._fn = this;
obj._fn();
}
6. .myCall要进行传值
Funtion.prototype.call实现代码版本2:
Function.prototype.myCall = function (obj,...rest) {
obj._fn = this;
obj._fn(...rest);
}
function testMycall(a,c,d) {
console.log(this.b + a + c +d);
}
var testObj1 = {
b: 'b val',
_fn:testMycall
} t
estMycall.myCall(testObj1,' a val',' c val',' d val');
7.function testMycall() {}中以return返回,则.myCall要return
8. 要删除._fn()这个属性。
Funtion.prototype.call实现代码版本3:
Function.prototype.myCall = function (obj,...rest) {
obj._fn = this;
let res = obj._fn(...rest);
delete obj._fn;
return res;
}
9.加个eval:
eval函数接收一个参数string,如果string不是字符串,则直接返回string。否则执行string语句。如果string语句执行结果是一个值,则返回此值,否则返回undefined。
最后就变成了最终代码。
与Function.prototype.call相关的功能实现
.apply的底层实现:
.apply只能传作为一个数组(或类似数组对象)提供的参数
Function.prototype.apply = function (obj, rest) {
var obj = obj || window;
obj._fn = this;
var res = eval('obj._fn(...rest)');
delete obj._fn
return res;
}
.bind的底层实现:
Function.prototype.bind = function (obj, ...rest) {
if (typeof this !== "function") {
throw new Error("this must be a function");
}
var self = this;
var fbound = function () {
self.apply(this instanceof self ? this : obj, rest.concat(Array.prototype.slice.call(arguments)));
}
if(this.prototype) {
fbound.prototype = Object.create(this.prototype);
}
return fbound;
}
new的底层实现:
function _new(ctor, ...args) {
if(typeof ctor !== 'function') {
throw 'ctor must be a function';
}
let obj = new Object();
obj.__proto__ = Object.create(ctor.prototype);
let res = ctor.apply(obj, [...args]);
let isObject = typeof res === 'object' && typeof res !== null;
let isFunction = typeof res === 'function';
return isObject || isFunction ? res : obj;
};
总结:
各位观众大老爷,该文有何不足,望 指出喔!
祝各位新年快乐,万事如意,一年比一年好。
最后来张图