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博客

相关文章
|
9天前
|
JavaScript 前端开发 开发者
call、bind、apply区别
【10月更文挑战第26天】`call`、`bind` 和 `apply` 方法在改变函数 `this` 指向和参数传递方面各有特点,开发者可以根据具体的需求和使用场景选择合适的方法来实现更灵活和高效的JavaScript编程。
15 1
|
1月前
|
前端开发 JavaScript
比较一下apply/call/bind ?
本文首发于微信公众号“前端徐徐”,详细介绍了 JavaScript 中 `apply`、`call` 和 `bind` 方法的概念、使用场景及手动实现。主要内容包括: - **apply**:使用数组作为参数调用函数,并指定 `this`。 - **call**:直接传递参数调用函数,并指定 `this`。 - **bind**:返回一个绑定了 `this` 和部分参数的新函数。 文章还对比了这三个方法的区别,并提供了手动实现的代码示例。
15 2
|
JavaScript 前端开发
面试官: call、apply和 bind有什么区别?
面试官: call、apply和 bind有什么区别?
|
6月前
call\apply\bind详解
call\apply\bind详解
32 0
bind、call、apply 区别
bind、call、apply 区别
77 0
call、apply、bind笔记
call、apply、bind笔记
62 0
apply、bind和call
apply、bind和call
87 0
|
JavaScript 前端开发
一文搞定this、apply、call、bind
一文搞定this、apply、call、bind