js进阶二(applycallbind闭包函数也是对象概念)

Posted 易辰_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js进阶二(applycallbind闭包函数也是对象概念)相关的知识,希望对你有一定的参考价值。

文章目录

apply\\call

apply和call可以改变this的指向

function f1(x, y) 
    console.log("结果是:" + (x + y) + this);
    return "10000";
  
  f1(10, 20);//函数的调用
  window.f1(10, 20);


  var r1 = f1.apply(null, [1, 2]);//此时f1中的this是window
  console.log(r1);

  var r2 = f1.call(null, 1, 2);//此时f1中的this是window
  console.log(r2);

  var obj = 
    age: 10,
    sex: "男"
  ;

  window.f1.apply(obj, [10, 20]);
  window.f1.call(obj, 10, 20);

输出如下:

结果是:30[object Window]
结果是:30[object Window]

结果是:3[object Window]
10000

结果是:3[object Window]
10000

结果是:30[object Object]
结果是:30[object Object]

我们在来看一个例子

function Person(age,sex) 
      this.age=age;
      this.sex=sex;
    
    //通过原型添加方法
    Person.prototype.sayHi=function (x,y) 
      console.log("您好啊:"+this.sex);
      return 1000;
    ;
    var per=new Person(10,"男");
    per.sayHi();

    console.log("==============");
    function Student(name,sex) 
      this.name=name;
      this.sex=sex;
    
    var stu=new Student("小明","人妖");
    var r1=per.sayHi.apply(stu,[10,20]);
    var r2=per.sayHi.call(stu,10,20);

    console.log(r1);
    console.log(r2);

输出如下:

您好啊:男
==============
您好啊:人妖
您好啊:人妖
1000
1000

函数也是对象

    function f1() 
      console.log(this+":====>调用了");
    
    //f1是函数,f1也是对象
    console.dir(f1);
    //对象调用方法,说明,该对象中有这个方法
    f1.apply();
    f1.call();
    console.log(f1.__proto__==Function.prototype);

输出如下:

ƒ f1()
[object Window]:====>调用了
[object Window]:====>调用了
true

bind

复制了一份的时候,把参数传入到了f1函数中,x===>10,y===>20,null就是this,默认就是window
bind方法是复制的意思,参数可以在复制的时候传进去,也可以在复制之后调用的时候传入进去
apply和call是调用的时候改变this指向
bind方法,是赋值一份的时候,改变了this的指向



  function f1(x, y) 
    console.log((x + y) + ":=====>" + this.age,this);
  

  var ff = f1.bind(null);
  ff(10, 20);

  //person对象
  function Person() 
    this.age = 1000;
  
  Person.prototype.eat = function () 
    console.log("这个是吃");
  ;
  var per = new Person();
  //传递person实例对象
  var ff = f1.bind(per, 10, 20);
  ff();

结果输出如下:

30:=====>undefined Window postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …
30:=====>1000 Person age: 1000

匿名函数返回值

function File(name, size, time) 
      this.name = name;//电影名字
      this.size = size;//电影大小
      this.time = time;//电影的上映时间
    
    var f1 = new File("jack.avi", "400M", "1997-12-12");
    var f2 = new File("tom.avi", "200M", "2017-12-12");
    var f3 = new File("xiaosu.avi", "800M", "2010-12-12");
    var f4 = new File("xiaosu.bvi", "800M", "2010-12-12");
    var arr = [f3,f4,f1, f2, ];

    function fn(attr) 
      //函数作为返回值
      return function getSort(obj1, obj2) 
        if (obj1[attr] > obj2[attr]) 
          return 1;
         else if (obj1[attr] == obj2[attr]) 
          return 0;
         else 
          return -1;
        
      
    

    var ff = fn("name");

    //函数作为参数
    arr.sort(ff);
    for (var i = 0; i < arr.length; i++) 
      console.log(arr[i].name + "====>" + arr[i].size + "===>" + arr[i].time);
    

输出如下:

jack.avi====>400M===>1997-12-12
tom.avi====>200M===>2017-12-12
xiaosu.avi====>800M===>2010-12-12
xiaosu.bvi====>800M===>2010-12-12

闭包

闭包可以缓存数据

 //普通的函数
  function f1() 
      var num = 10;
      num++;
      return num;
    
    console.log(f1());
    console.log(f1());
    console.log(f1());

    //函数模式的闭包
    function f2() 
      var num = 10;
      return function () 
        num++;
        return num;
      
    
    var ff = f2();
    console.log(ff());//11
    console.log(ff());//12
    console.log(ff());//13

输出如下:

11
11
11
11
12
13

我们来看另外一个例子

function count() 
    var arr = [];
    for (var i=1; i<=3; i++) 
        arr.push(function () 
            return i * i;
        );
    
    return arr;


var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];

console.info(f1())
console.info(f2())
console.info(f3())

输出均为16

原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了4,因此最终结果为16。

返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。



function count() 
    var arr = [];
    for (var i=1; i<=3; i++) 
        arr.push((function (n) 
            return function () 
                return n * n;
            
        )(i));
    
    return arr;



var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];

console.info(f1())
console.info(f2())
console.info(f3())

输出1 4 9

闭包不仅可以为了返回一个函数然后延迟执行
在面向对象的程序设计语言里,比如Java和C++,要在对象内部封装一个私有变量,可以用private修饰一个成员变量。

在没有class机制,只有函数的语言里,借助闭包,同样可以封装一个私有变量。我们用javascript创建一个计数器:

function create_counter(initial) 
    var x = initial || 0;
    return 
        inc: function () 
            x += 1;
            return x;
        
    

它用起来像这样:

var c1 = create_counter();
c1.inc(); // 1
c1.inc(); // 2
c1.inc(); // 3

var c2 = create_counter(10);
c2.inc(); // 11
c2.inc(); // 12
c2.inc(); // 13

在返回的对象中,实现了一个闭包,该闭包携带了局部变量x,并且,从外部代码根本无法访问到变量x。换句话说,闭包就是携带状态的函数,并且它的状态可以完全对外隐藏起来。

以上是关于js进阶二(applycallbind闭包函数也是对象概念)的主要内容,如果未能解决你的问题,请参考以下文章

JS面试题(进阶)——原型链、this指向、闭包

python函数之进阶 函数嵌套,命名空间,闭包

javascript进阶笔记

javascript进阶笔记

函数进阶之闭包函数和装饰器

JS:applycallbind的区别