zoukankan      html  css  js  c++  java
  • 深入了解new的过程,和call,apply,bind的区别

    话不多数,直接上代码

      1 //1、new的过程发生了什么
      2     function create () {
      3         //创建了一个对象
      4         var obj = new Object()
      5         //获取构造函数
      6         //shift用于把数组的第一个元素删除,并且返回第一个元素的值
      7         var Con = [].shift.call(arguments)
      8         //链接到原型
      9         obj.__proto__ = Con.protoptype
     10         //绑定this的指向
     11         let result = Con.apply(obj,arguments)
     12         //返回一个新的对象
     13         return typeof result === 'object' ? result : obj
     14     }
     15     //2、call、apply,bind的区别和用法
     16     var a = 1
     17     var obj = {
     18         a:2,
     19         fn () {
     20             console.log(this)
     21         }
     22     }
     23     //obj.fn.call(obj)
     24     //打印obj
     25     //会立即调用改变this的指向,普通函数this的指向指向调用它的那个对象
     26     //obj.fn.apply(obj)
     27     //f1.call(null,f2)
     28     var a = 1
     29     var obj2 = {
     30         a:2,
     31         fn () {
     32             console.log(this.a)
     33         }
     34     }
     35     //obj2.fn()
     36     //---2
     37     //var fn1 = obj2.fn
     38     //fn1()
     39     //---1
     40     //相信大家会有一点困惑,第一次this就指向它本身,自己调用,第二次this指向window
     41     //如果你传的context就null或者undefined,那么window对象就是默认的context(严格模式context就是undefined)
     42     //这也叫隐式的绑定,如果你希望打印2,修改为fn1.call(obj)
     43     //回调函数this的指向指向window
     44     //构造器模式,new一个函数时候,背地里会将新建的对象连接到prototype里,同时this会被绑定到那个对象上
     45     //call--方法第一个参数是绑定给this的值,后面传入的是一个参数的列表
     46     var obj3 = {
     47         message:'我的名字是:'
     48     }
     49     function getName (firstnmae,lastname) {
     50         console.log(this.message+firstnmae+''+lastname)
     51     }
     52     //getName.call(obj3,'武','泉')
     53     //apply--接受两个参数,第一个是要绑定this的值,第二个是一个参数数组
     54     var arr = [1,2,3,4,5,6]
     55     var max = Math.max.apply(this,arr)
     56     //console.log(max)
     57     //当第一个传入的是this,null,undefined时可以打印的是6
     58     //这里使用call打印的是NaN
     59     //bind--返回的是函数,不会被立即执行,返回的是一个改变了上下文this后的函数
     60     function bindfn (a,b,c) {
     61         console.log(a,b,c)
     62     }
     63     var binffn1 = bindfn.bind(this,'Doc')
     64     //binffn1('A','B','C')
     65     //Doc A B
     66     //binffn1('B','C')
     67     //Doc B C
     68     //说明bind后面的参数作为实参传进去了,后面的参数排队进
     69     //用bind实现函数珂里化
     70     var add = function (x) {
     71         return function(y){
     72             return x+y
     73         }
     74     }
     75     var addTen = add(9)
     76     //console.log(addTen(1))
     77     //10
     78     //低版本里没有bind,那么就自己手写一个
     79     if(!Function.prototype.bind){
     80         Function.prototype.bind = function () {
     81             //保留原函数
     82             var self = this
     83             //保存需要绑定this指向的上下文
     84             var context = [].shift.call(arguments)
     85             //剩余的参数转化为数组
     86             var args = [].slice.call(arguments)
     87             return function () {
     88                 //解释一哈,返回一个新的函数,把context指向self,参数是上边保存的参数,拼接到一起
     89                 self.apply(context,[].concat.call(args,[].slice.call(arguments)))
     90             }
     91         }
     92     }
     93     //[]就和Array.prototype差不多
     94     //console.log([]==Array)
     95     //false
     96     //console.log([] instanceof Array)
     97     //true
     98     //应用场景
     99     //求数组最大最小
    100     var arr = [1,2,3,89,46]
    101     var max = Math.max.apply(null,arr)//89
    102     var min = Math.min.apply(null,arr)//1
    103     //将伪数组转化为数组
    104     var trueArr = Array.prototype.slice.call(arrLike)
    105     //数组追加
    106     var arr1 = [1,2,3];
    107     var arr2 = [4,5,6];
    108     var total = [].push.apply(arr1, arr2);//6
    109     // arr1 [1, 2, 3, 4, 5, 6]
    110     // arr2 [4,5,6]
    111     //判断变量类型
    112     function isArray(obj){
    113         return Object.prototype.toString.call(obj) == '[object Array]';
    114     }
    115     isArray([]) // true
    116     isArray('dot') // false
    117     //利用call和apply做继承
    118     function Person(name,age){
    119         // 这里的this都指向实例
    120         this.name = name
    121         this.age = age
    122         this.sayAge = function(){
    123             console.log(this.age)
    124         }
    125     }
    126     function Female(){
    127         Person.apply(this,arguments)//将父元素所有方法在这里执行一遍就继承了
    128     }
    129     var dot = new Female('Dot',2)

     他说少于150字不允许发。。。

    bind返回对应函数, 便于稍后调用; apply, call则是立即调用。

    除此外, 在 ES6 的箭头函数下, call 和 apply 将失效, 对于箭头函数来说:

    • 箭头函数体内的 this 对象, 就是定义时所在的对象, 而不是使用时所在的对象;所以不需要类似于var _this = this这种丑陋的写法
    • 箭头函数不可以当作构造函数,也就是说不可以使用 new 命令, 否则会抛出一个错误
    • 箭头函数不可以使用 arguments 对象,,该对象在函数体内不存在. 如果要用, 可以用 Rest 参数代替
    • 不可以使用 yield 命令, 因此箭头函数不能用作 Generator 函数,什么是Generator函数可自行查阅资料,推荐阅读阮一峰Generator 函数的含义与用法Generator 函数的异步应用
  • 相关阅读:
    Node自动重启工具 nodemon
    centos 集群
    kettle操作数据库增删改
    Dinic
    vim
    mermaid简介
    联赛模拟测试32
    检讨书模板
    博客园如何添加看板娘!
    手机浏览器如何调试
  • 原文地址:https://www.cnblogs.com/quanquanchacha/p/9971663.html
Copyright © 2011-2022 走看看