new bind apply call instanceof 等笔记

简介: new bind apply call instanceof 等笔记


call和apply的用途
Function.prototype.call 和 Function.prototype.apply 都是非常常用的方法。它们的作用一模一样,区别仅在于传入参数形式的不同

方法 apply call
第一个参数 函数体内 this 对象的指向 函数体内 this 对象的指向
第二个参数 带下标的集合 从第二个参数开始,每个参数被依次传入函数
apply

var func = function( a, b, c ){
alert ( [ a, b, c ] ); // 输出 [ 1, 2, 3 ]
};
func.apply( null, [ 1, 2, 3 ] );
call

var func = function( a, b, c ){
alert ( [ a, b, c ] ); // 输出 [ 1, 2, 3 ]
};
func.call( null, 1, 2, 3 );
//实现一个 将类数组 或对象 转化对 真正数组

function array(a, n){
return Array.prototype.slice.call(a, n || 0)
}

//应用: 这个函数的实参传至左侧
function partialLeft (f /,.../){

var args = arguments;
return function(){
var a =array(args,1);
a = a.concat(array(arguments));
return f.apply(this,a)
}

}

call和apply的用途
改变 this 指向
借用其他对象的方法
改变 this 指向

var obj1 = {
name: 'sven'
};
var obj2 = {
name: 'anne'
};
window.name = 'window';
var getName = function(){
alert ( this.name );
};
getName(); // 输出:window
getName.call( obj1 ); // 输出: sven
getName.call( obj2 ); // 输出: anne

借用其他对象的方法

(function(){
Array.prototype.push.call( arguments, 3 );
console.log ( arguments ); // 输出[1,2,3]
})( 1, 2 );

Function.prototype.myCall = function(context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
context = context || window;console.log('context==>',context)
context.fn = this;console.log("context.fn==>",context.fn,"this==>",this)
const args = [...arguments].slice(1);console.log('arg==>s',args);
const result = context.fn(...args)
delete context.fn; console.log('result==>',result)
return result
}
//准备两个方法来玩一下
function add(a,b){
return a+b;
}
function sub(a,b){
return a-b;
}
//控制台打印
add.myCall(sub,32,122) //sub 调用add方法
context==> ƒ sub(a,b){
return a-b;
}
context.fn==> ƒ add(a,b){
return a+b;
} this==> ƒ add(a,b){
return a+b;
}
arg==>s (2) [32, 122]
result==> 154
154
//以下是对实现的分析:

//首先 context 为可选参数,如果不传的话默认上下文为 window
//接下来给 context 创建一个 fn 属性,并将值设置为需要调用的函数
//因为 call 可以传入多个参数作为调用函数的参数,所以需要将参数剥离出来
//然后调用函数并将对象上的函数删除

//apply() 实现

Function.prototype.myApply = function(context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
context = context || window
context.fn = this
let result
// 处理参数和 call 有区别
if (arguments[1]) {
result = context.fn(...arguments[1])
} else {
result = context.fn()
}
delete context.fn
return result
}
//apply 用于实现继承
function Animal(name){
this.name = name;
this.showName = function(){
alert(this.name);
}
}

function Cat(name){
Animal.apply(this,[name]);
}

var cat = new Cat("咕咕");
cat.showName();

/call的用法/
Animal.call(this,name);

bind() 方法
bind()在EC5中新增的方法。这个方法的主要作用就是将函数绑定至某个对象。

function f(y) { return this.x + y} //这个是待绑定的方法

var o = { x : 1};//将要绑定的对象

var g = f.bind(o) ; // 通过调用g(x)来调用 o.f(x)

g(2 ) // ==> 3

//其他例子

this.num = 9;
var mymodule = {
num: 81,
getNum: function() { return this.num; }
};

module.getNum(); // 81

var getNum = module.getNum;
getNum(); // 9, 因为在这个例子中,"this"指向全局对象

// 创建一个'this'绑定到module的函数
var boundGetNum = getNum.bind(module);

题外疑问:最近读到var a = Function.prototype.bind() ; 这个函数a没有 prototype的 即a.prototype 没有

所以我用下面的方法 var c = Function.prototype.mybind1() 却带有 c.prototype

所以 Function.prototype.myBind1() === Function.prototype.bind() //false

// 通过如下代码实现这种绑定
Function.prototype.myBind1 = function (context) { console.log('this==>',this)
if (typeof this !== 'function') {
throw new TypeError('Error')
}
const _this = this
const args = [...arguments].slice(1);console.log("args==>",args)
// 返回一个函数
return function F() {
// 因为返回了一个函数,我们可以 new F(),所以需要判断
if (this instanceof F) { console.log('F==>',F)
return new _this(...args, ...arguments)
} console.log('result==>',_this.apply(context, args.concat(...arguments)))
return _this.apply(context, args.concat(...arguments))
}
}

new

//在调用 new 的过程中会发生以上四件事情:
//新生成了一个对象
//链接到原型
//绑定 this
//返回新对象
//根据以上几个过程,我们也可以试着来自己实现一个 new

function Person(name,age){
  this.name = name;
  this.age = age;
}

function create() {
// 创建一个空的对象
let obj = new Object()
// 获得构造函数
let Con = [].shift.call(arguments)
// 链接到原型
obj.proto = Con.prototype
// 绑定 this,执行构造函数
let result = Con.apply(obj, arguments)
// 确保 new 出来的是个对象
return typeof result === 'object' ? result : obj
}

var p2 = create(Person,"涛涛",333) //等同于 var p2 =new Person("涛涛",333)

p2//==> Person {name: "涛涛", age: 333}

以下是对实现的分析:

创建一个空对象
获取构造函数
设置空对象的原型
绑定 this 并执行构造函数
确保返回值为对象
对于对象来说,其实都是通过 new 产生的,无论是 function Foo() 还是 let a = { b : 1 } 。

对于创建一个对象来说,更推荐使用字面量的方式创建对象(无论性能上还是可读性)。因为你使用 new Object() 的方式创建对象需要通过作用域链一层层找到 Object,但是你使用字面量的方式就没这个问题。

function Foo() {}
// function 就是个语法糖
// 内部等同于 new Function()
let a = { b: 1 }
// 这个字面量内部也是使用了 new Object()

instanceof
instanceof 可以正确的判断对象的类型,因为内部机制是通过判断对象的原型链中是不是能找到类型的 prototype。

我们也可以试着实现一下 instanceof

function myInstanceof(left, right) {
let prototype = right.prototype;console.log('prototype--',prototype)
left = left.proto ;console.log('left--',left)
while (true) {
if (left === null || left === undefined)
return false
if (prototype === left)
return true
left = left.proto
}
}

var a = {}
a instanceof Object //true

myInstanceof(a,Object) // true 可以自行尝试下

以下是对实现的分析:

首先获取类型的原型
然后获得对象的原型
然后一直循环判断对象的原型是否等于类型的原型,直到对象原型为 null,因为原型链最终为 null
参考 : https://juejin.im/post/5c0d15a3f265da612e2876a2

参考 :bind()_前进的探索者的博客-CSDN博客

相关文章
|
8天前
|
JavaScript 前端开发 测试技术
手写call , apply , bind 方法的实现
本文通过实例讲解了JavaScript中`call`、`apply`及`bind`方法的用途与实现。以`call`为例,展示了如何改变函数内的`this`指向,并立即执行该函数。通过在`Function.prototype`上定义`myCall`,利用`Symbol`确保新增属性的唯一性,从而避免命名冲突。接着介绍了如何处理不定数量的参数传递,最终实现了自定义的`myCall`方法。随后简述了`apply`与`call`的区别,并展示了其实现方式,主要在于参数传递形式的不同。最后,通过`bind`方法创建了一个返回新函数的例子,该新函数具有固定的`this`上下文,同时支持分批参数传递。
14 2
手写call , apply , bind 方法的实现
|
3月前
call\apply\bind详解
call\apply\bind详解
19 0
|
12月前
|
JavaScript 前端开发
面试官: call、apply和 bind有什么区别?
面试官: call、apply和 bind有什么区别?
bind、call、apply 区别
bind、call、apply 区别
66 0
call、apply、bind笔记
call、apply、bind笔记
53 0
apply、bind和call
apply、bind和call
74 0
|
JavaScript 前端开发
一文搞定this、apply、call、bind
一文搞定this、apply、call、bind