函数方法bind、call、apply的实现,再加一个String对象的trim方法
这3个东东,是骆驼是马,拉出来遛一遛
相同点:
都可以改变函数体内部this的指向。
区别:
- bind改变this指向后return一个函数,不会立即执行。var fn = func.bind(obj, a, b); fn();
call apply 改变this指向后会立即执行函数。func.call(obj, a, b); func.apply(obj,
[a,b]); - bind、call的参数是一个一个传进去的,而apply的参数需要放到数组里面。
用原生实现
思路:
var student = {name: "baby", age: 1};
function fn (name, age) {
this.name = name;
this.age = age;
}
fn.bind(student, "roy", 18);
我们都知道fn调用的bind是在其原型Function对象中找到的。
fn.__proto__ == Fuction.prototype
为了让函数都能调用到我们实现的bind方法,我们也将方法添加到Function.prototype,为了区别与原有的bind,我们就叫_bind。
Function.prototype._bind = function(target, ...params)
{
target.func = this; //this 指向 fn.bind()的fn方法
return function() {
target.func(...params); //执行方法,func函数中的this指向target对象
}};
let f1 = fn._bind(student, "bind", 19);
f1();
Function.prototype._call = function (target, ...params) {
target.func = this;
return (function() {
target.func(...params);
})()
}
fn._call(student, "call", 20);
Function.prototype._apply = function (target, params) {
target.func = this;
return (function() {
target.func(...params);
})()
}
fn._apply(student, ["apply", 22]);
到这里,就用原生实现了bind、call和apply方法了。
实现String对象的trim方法
//包装对象,字符串不是对象,但是引用字符串的属性时,
//JavaScript就会将字符串值通用调用New String(s)转换成String对象,
//继承了String对象的所有方法,一旦引用结束这个新创建的对象就会被销毁。
//s._trim(),s转换为了String对象,所以这里的this是String对象
String.prototype._trim = function() {
var str = this;
console.log(str);
if(str && str instanceof String) {
var headSpace = true;
var trimStr = [];
for(var i=0; i < str.length; i++){
if(headSpace) {
if(str[i] == " "){
continue;
}else{
headSpace = false;
trimStr.push(str[i]);
}
}else{
trimStr.push(str[i]);
}
}
for(var i=trimStr.length - 1; i > 0; i--) {
if(trimStr[i] == " "){
trimStr.pop();
}else{
break;
}
}
return trimStr.join("");
}else{
return null;
}
}
var s=" abc ";console.log(s._trim());
s=" ";console.log(s._trim());
s="ab cd e ";console.log(s._trim());
s="";console.log(s._trim());