Reference link: github.com/mqyqingfeng…
1. call
Pass in any parameters and execute immediately
Call a function or method with a specified this value and a number of specified parameter values:
var foo = { value : 1}
function bar(){
console.log(this.value)
}
bar.call(foo)// 1
// call 改变了 this 的指向,指向了 foo;
// bar 函数执行了;
复制代码
To achieve the specified this value, the simulation steps are divided into:
- Set the function as a property of the object;
- execute the function;
- delete the function;
Function.prototype.call = function(context){
// 获取调用 call 的函数,用 this 可以获取
console.log(this)// bar(){ console.log( this.value ) }
context.fn = this
context.fn()
delete context.fn
}
// 测试一下
var foo = { value : 1 }
function bar(){
console.log(this.value)
}
bar.call(foo)// 1,相当于foo.bar()
复制代码
Implements several specified parameter values:
- Get the value from the Arguments object, take the second to last arguments, and put them in an array
Function.prototype.call = function(context){
context.fn = this
var args = [...arguments].slice(1)
context.fn(...args)
delete context.fn
}
// 测试一下
var foo = { value : 1 }
function bar(name,age){
console.log(this.value)
console.log(name)
console.log(age)
}
bar.call(foo,'zouyan','18')
// 1
// zouyan
// 18
复制代码
optimization:
- This parameter can be passed null, when it is null, it is regarded as pointing to the window;
- Functions can have return values;
Function.prototype.call = function(context) {
var context = context || window
context.fn = this
var args = [...arguments].slice(1)
var result = context.fn(...args)
delete context.fn
return result
}
// 测试一下
var value = 2
var foo ={ value : 1 }
function bar(name,age){
console.log(this.value)
return{
value: this.value,
name: name,
age:age
}
}
bar.call(null)// 2
bar.call(foo,'zouyan',18)// {value:1,name:'zouyan',age:'18'}
复制代码
2. apply
Pass in the parameter array and execute it immediately
Function.prototype.apply = function(context, arr) {
var context = Object(context) || window
context.fn = this
var result
if (!arr) {
result = context.fn()
} else {
var args = arr || []
result = context.fn(...args)
}
delete context.fn
return result
}
// 测试一下
var value = 2
var foo ={ value : 1 }
function bar(name,age){
console.log('value',this.value)
return{
value: this.value,
name: name,
age:age
}
}
bar.apply(null)
bar.apply(foo,['zouyan',18])// {value:1,name:'zouyan',age:'18'}
复制代码
3. bind
Pass in parameters and return functions, which need to be executed manually
- The bind() method creates a new function;
- Pass in the first parameter of bind as this when it runs;
- The other parameters passed in are used as the parameters of the function runtime;
- Two features: return a function that can pass in parameters;
// 模拟返回函数:
Function.prototype.bind = function(cxt){
var self = this
return function(){
return self.apply(cxt)
}
}
// 模拟传参
Function.prototype.bind = function(cxt){
var self = this
// 获取 bind 函数从第二个参数到最后一个参数
var args = [].slice.call(arguments, 1)
return function(){
// arguments 指 bind 返回的函数传入的参数
var newArgs = args.concat([].slice.call(arguments))
return self.apply(cxt, newArgs)
}
}
复制代码
A bound function can also create objects using the new operator: this acts as if the original function were a constructor. The supplied this value is ignored, and the arguments are supplied to the mock function at the time of invocation.
// 模拟实现构造函数
Function.prototype.bind = function(cxt){
var self = this
var args = [].slice.call(arguments, 1)
var fNOP = function(){}
var fBound = function(){
var newArgs = args.concat([].slice.call(arguments))
return self.apply(this instanceof fNOP ? this : cxt, newArgs)
}
fNOP.prototype = this.prototype
fBound.prototype = new fNOP()
return fBound
}
// 调用 bind 函数,不是函数则报错
// 兼容
Function.prototype.bind = function(cxt){
if(typeof this !== "function"){
throw new Error("is not a function")
}
var self = this
var args = [].slice.call(arguments, 1)// 获取第二个参数到最后一个参数
var fNOP = function(){}
var fBound = function(){
var newArgs = args.concat([].slice.call(arguments))
return self.apply(this instanceof fNOP ? this : cxt, newArgs)
}
fNOP.prototype = this.prototype
fBound.prototype = new fNOP()
return fBound
}
复制代码
4. new
- Instances can access properties in the constructor;
- Instances can access properties in the constructor prototype;
Implementation steps:
- ① Create a new object obj: because the result of new is a new object;
- ②The
obj._proto_
property points to the prototype of the constructor: because the instance needs to access the properties on the prototype; - ③ Use apply to add new properties to obj: because obj has properties in the constructor;
- ④ Judging whether the return value is an object, it is an object that returns an object, otherwise it returns obj: the constructor may have a return value;
// 模拟实现 new 关键字
function objectFactory() {
// 步骤 ①
var obj = new Object(),//存疑,为什么模拟new里面使用new?
//var obj = Object.create(null),//报错:TypeError
//var obj = {},//正常
//var obj = Object.create({}),//正常
//var obj = Object.create(Object.prototype),//正常
// 步骤 ②
// 获取构造函数,截取第一个参数;
// shift 会修改原数组,所以 arguments 会被去除的一个参数;
Constructor = [].shift.call(arguments);// 等同于 Array.prototype.shift.call(arguments)
obj.__proto__ = Constructor.prototype;
var ret = Constructor.apply(obj, arguments); // 步骤 ③
return typeof ret === 'object' ? ret||obj : obj; // 步骤 ④
};
// 构造函数
function Otaku (name, age) {
this.name = name;
this.age = age;
this.habit = 'Games';
}
Otaku.prototype.strength = 60;
Otaku.prototype.sayYourName = function () {
console.log('I am ' + this.name);
}
// 模拟创建实例
var person = objectFactory(Otaku, 'Kevin', '18')
console.log(person.name) // Kevin
console.log(person.habit) // Games
console.log(person.strength) // 60
person.sayYourName(); // I am Kevin
复制代码