理解JavaScript(5):关于之前的文章没有提到的一些重要的知识点

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cdzmy/article/details/80689766

补充

前面的内容都是一块一块的,有些遗漏的地方,在此博客中慢慢补充

this 关键字

this 要在执行时才能确认,this指向调用这个函数或方法的对象

this的使用场景

  • 作为构造函数执行,this指向构造对象
function game (name) {
    this.name = name;
}
var dota2 = new game('dota2');
console.log(doat2.name) // dota2 this指向dota2
  • 作为对象属性执行,this指向调用对象本身
var math = {
    x: 0;
    y: 1;
    add: function () {
        console.log(this.x + this.y);
    }
}
math.add(); // this指向math
  • 作为普通函数执行,this指向window(浏览器环境下)
window.name = 'The Window';
function add (x, y) {
    console.log(this.name);
}
add(0, 1) // The Window this指向window
  • 在call,apply,bind后面使用,this指向call,apply,bind参数里面的对象
var a = {
    x: 0,
    y: 0,
    add: function () {
        var result = this.x + this.y;
        console.log(this);
        console.log(result);
    }
}
var b = {
    x: 1,
    y: 5
}
a.add.call(b); //{x:1,y:5} 6 this指向对象b

apply,call,bind改变函数作用域

  • apply和call函数
    每个函数都包含非继承而来的apply和call方法,这两个方法的作用是一样的,都是在特定的作用域调用函数,等于设置函数体内的this对象值,代表函数运行的作用域。使用如上面的代码所示。不同点是:apply()方法 接收两个参数,一个是函数运行的作用域(this),另一个是参数数组。call()方法 第一个参数和apply()方法的一样,但是传递给函数的参数必须列举出来。

    下面就让我们来模拟实现这两个函数:
Function.prototype.myCall = function (context) {
    var context = context || window;
    context.fn = this;
    var args = [];
    for (var i = 1; i < args.length; i++) {
        args.push('arguments[' + i + ']');
    }
    var result = eval('context.fn(' + args + ')');
    delete context.fn;
    return result;
}
Function.prototype.myApply = function (context, arr) {
    var context = context;
    context.fn = this;
    if (!arr) {
        context.fn();
    } else {
        context.fn(arr);
    }
    delete context.fn;
    return result;
}
  • bind函数
    bind()函数会创建一个新函数(称为绑定函数),新函数和绑定函数的目标函数具有相同的函数体。当新函数被调用,this值指向bind()函数的第一个参数,该参数不能被重写。新函数被调用时,bind()也接受预设的参数提供给原函数。一个绑定的函数也能使用new操作符创建对象;这种行为就像把目标函数当做构造器,提供的this值被忽略,同时调用时的参数被提供给新函数。实现一个bind()函数需要注意一下几点。
    1. 因为bind函数不会立即执行, 需要返回一个待执行的函数(闭包)
    2. 作用域绑定,这里可以使用apply和call方法来实现
    3. 参数传递,由于后面的参数传递的不确定性需要用apply传递数组
    4. 继承被实例化函数的原型
Function.prototype.testBind = function (that) {
    var _this = this,
        slice = Array.prototype.slice,
        args = slice.apply(arguments, [1]),
        fn = function () {},
        bound = function () {
            return _this.apply(that, args.concat(slice.apply(arguments, [0])))
        }
    fn.prototype = _this.prototype;
    bound.prototype = new fn();
    return bound;
}
var test = function (a, b) {
    console.log('作用域绑定', this.value);
    console.log('testBind参数传递', a.value2);
    console.log('调用参数传递', b);
}
var obj = {value: 'ok'}
var fun_new = test.testBind(obj, {value2: 'also Ok'});
fun_new('hello bind');
// 作用域绑定 ok
// testBind参数传递 also ok
// 调用参数传递 hello bind
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页