深入之bind的模拟实现,JavaScript深入之bind的模拟实现

JavaScript 深刻之bind的效仿完结

2017/05/26 · JavaScript
· bind

原作出处: 冴羽   

已离开简书,原因参见
http://www.jianshu.com/p/0f12350a6b66。

初稿出处

新普京娱乐网址,JavaScript深刻之bind的效仿完成

JavaScript 深切之new的依样葫芦完毕

2017/05/26 · JavaScript
· new

原来的小说出处: 冴羽   

bind

一句话介绍 bind:

bind() 方法会创设四个新函数。当以此新函数被调用时,bind()
的率先个参数将作为它运营时的
this,之后的一连串参数将会在传递的实参前流传作为它的参数。(来自于 MDN
)

经过大家得以率先得出 bind 函数的五个特点:

  1. 深入之bind的模拟实现,JavaScript深入之bind的模拟实现。回来3个函数
  2. 能够流传参数

虽人微权轻,但也要有温馨的千姿百态。

bind

笔者们在模仿 bind从前,先看看 bind实现了何等成效。

        var foo = {
            value: 1
        };

        function bar() {
            console.log(this.value);
        }

        // 返回了一个函数
        var bindFoo = bar.bind(foo);

        bindFoo(); // 1

经过我们得以率先得出 bind 函数的多少个特色:

  1. 回到一个函数
  2. 改变了this的指向

new

一句话介绍 new:

new
运算符创设叁个用户定义的指标类型的实例或持有构造函数的放权对象类型之一

或是有点难懂,大家在模仿 new 以前,先看看 new 完结了何等职能。

举个例证:

// Otaku 御宅族,简称宅 function Otaku (name, age) { this.name = name;
this.age = age; this.habit = ‘加梅斯’; } //
因为不够锻练的原由,身体强度令人担忧 Otaku.prototype.strength = 60;
Otaku.prototype.sayYourName = function () { console.log(‘I am ‘ +
this.name); } var person = new Otaku(‘凯文’, ’18’);
console.log(person.name) // 凯文 console.log(person.habit) // 加梅斯console.log(person.strength) // 60 person.sayYourName(); // I am 凯文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Otaku 御宅族,简称宅
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 = new Otaku(‘Kevin’, ’18’);
 
console.log(person.name) // Kevin
console.log(person.habit) // Games
console.log(person.strength) // 60
 
person.sayYourName(); // I am Kevin

从这几个事例中,大家得以看来,实例 person 能够:

  1. 访问到 Otaku 构造函数里的属性
  2. 做客到 Otaku.prototype 中的属性

接下去,大家能够品尝着模拟一下了。

因为 new 是第2字,所以不或然像 bind
函数一样直接覆盖,所以我们写三个函数,命名为 objectFactory,来效仿 new
的效用。用的时候是如此的:

function Otaku () { …… } // 使用 new var person = new Otaku(……); // 使用
objectFactory var person = objectFactory(Otaku, ……)

1
2
3
4
5
6
7
8
function Otaku () {
    ……
}
 
// 使用 new
var person = new Otaku(……);
// 使用 objectFactory
var person = objectFactory(Otaku, ……)

再次回到函数的效仿实现

从第三个特色起头,大家举个例子:

var foo = { value: 1 }; function bar() { console.log(this.value); } //
再次回到了一个函数 var bindFoo = bar.bind(foo); bindFoo(); // 1

1
2
3
4
5
6
7
8
9
10
11
12
var foo = {
    value: 1
};
 
function bar() {
    console.log(this.value);
}
 
// 返回了一个函数
var bindFoo = bar.bind(foo);
 
bindFoo(); // 1

关于钦点 this 的指向,大家得以运用 call 或然 apply 贯彻,关于 call 和
apply
的效仿实现,能够查看《JavaScript深远之call和apply的模仿完毕》。大家来写第二版的代码:

// 第一版 Function.prototype.bind2 = function (context) { var self =
this; return function () { self.apply(context); } }

1
2
3
4
5
6
7
8
// 第一版
Function.prototype.bind2 = function (context) {
    var self = this;
    return function () {
        self.apply(context);
    }
 
}

小说能够在本人的 Github
https://github.com/mqyqingfeng/Blog
查看

仿照完毕率先步


          var foo = {
            value: 1
        };

        function bar() {
            console.log(this.value);
        }
        // 第一版
        Function.prototype.bind2 = function (context) {
            var self = this;
            return function () {  // 返回一个函数
            return self.apply(context);  // 改变绑定函数的this指向
            }

        }

        // 返回了一个函数
        var bindFoo = bar.bind2(foo);
        bindFoo();  // 1

起来达成

分析:

因为 new
的结果是一个新对象,所以在模仿达成的时候,大家也要赤手空拳一个新目的,若是这些目的叫
obj,因为 obj 会具有 Otaku
构造函数里的习性,想想经典接二连三的例证,我们能够使用 Otaku.apply(obj,
arguments)来给 obj 添加新的属性。

在 JavaScript 深远种类第三篇中,大家便讲了原型与原型链,大家知道实例的
__proto__ 属性会指向构造函数的
prototype,也正是因为建立起这么的关系,实例能够访问原型上的特性。

方今,我们得以品味着写第叁版了:

// 第壹版代码 function objectFactory() { var obj = new Object(),
Constructor = [].shift.call(arguments); obj.__proto__ =
Constructor.prototype; Constructor.apply(obj, arguments); return obj; };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 第一版代码
function objectFactory() {
 
    var obj = new Object(),
 
    Constructor = [].shift.call(arguments);
 
    obj.__proto__ = Constructor.prototype;
 
    Constructor.apply(obj, arguments);
 
    return obj;
 
};

在这一版中,我们:

  1. 用new Object() 的办法新建了1个对象 obj
  2. 取出第二个参数,正是我们要传播的构造函数。其余因为 shift
    会修改原数组,所以 arguments 会被删去第二个参数
  3. 将 obj 的原型指向构造函数,那样 obj 就能够访问到构造函数原型中的属性
  4. 应用 apply,改变构造函数 this 的针对性到新建的指标,那样 obj
    就足以访问到构造函数中的属性
  5. 返回 obj

越多关于:

原型与原型链,能够看《JavaScript深刻之从原型到原型链》

apply,可以看《JavaScript深远之call和apply的模仿达成》

经文一而再,能够看《JavaScript深远之继续》

复制以下的代码,到浏览器中,大家得以做一下测试:

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); } function objectFactory() { var obj = new Object(),
Constructor = [].shift.call(arguments); obj.__proto__ =
Constructor.prototype; Constructor.apply(obj, arguments); return obj; };
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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);
}
 
function objectFactory() {
    var obj = new Object(),
    Constructor = [].shift.call(arguments);
    obj.__proto__ = Constructor.prototype;
    Constructor.apply(obj, arguments);
    return obj;
};
 
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

[]~( ̄▽ ̄)~**

相关文章