avaScript学习(七)

构造函数

箭头函数不能用来做构造函数,箭头函数没有this,不能new
构造函数首字母一般大写,使用大驼峰命名

function Person (name) {
      // 构造函数里的this指向将来new的那个对象
      this.name = name // 给this对象新增一个name属性,属性值为参数name
      this.say = function () {
        console.log(this.name)
      }
    }

    // Person()

    var xm = new Person('xiaoming')
    console.log(xm)
    xm.say()

    var xh = new Person('xiaohong')
    console.log(xh)
    xh.say()
 function Person (name) {
      this.name = name
      this.say = function () {
        console.log(this.name)
      }
    }

    // 给Person的原型对象上新增eat方法
    Person.prototype.eat = function (food) {
      // 原型方法的this也是指向将来的实例对象
      console.log(`${this.name} is eating ${food}`)
    }

    var xm = new Person('xiaoming')
    var xh = new Person('xiaohong')
    // 构造函数里的方法不能复用,每个实例对象里都存了一份一摸一样的方法,浪费内存
    console.log(xm.say === xh.say) //false

    console.log(Person)
    console.dir(Person) //用来打印对象的详细信息,可以发现会有prototype 和 __proto__两个属性  实例对象的__ptoto__指向构造函数的prototype

    // 实例对象可以调用原型上的方法
    xm.eat('rice')
    xh.eat('noodles')

    console.log(xm.eat === xh.eat)

    console.log(xm)

    // 实例对象都有__proto__属性,这个属性指向构造函数的prototype
    console.log(xm.__proto__ === Person.prototype) // true

    // console.log(xm.toString())
    // person的原型也是一个普通对象,就相当于来自于new Object(),所以他也有__proto__属性,这个属性指向Object.prototype
    console.log(Person.prototype.__proto__ === Object.prototype)

    console.log(Object.prototype.__proto__) // null

    // 对象沿着原型一层一层往上查找的过程称之为原型链
    // 所有原型链的终点都是Object.prototype
    // js中任意数据都可以沿着自己的原型链最终找到Object.prototype,因此,一切皆为对象
    // js中顶级对象就是Object,Object是所有对象里基类

当new去调用函数的时候,实际上new帮我们做了四件事

  // 下面这些代码是伪代码,不能执行,只是演示过程
    // function Animal (name) {
    //   // 1、new一个对象
    //   var obj = new Object()
    //   // 2、把this指向这个对象
    //   this = obj
    //   // 3、执行函数代码
    //   this.name = name
    //   // 4、返回这个对象
    //   return this
    // }

给原型添加方法

    Object.assign(Animal.prototype, {
      say () {
      },
      init () {
      }
    })
function Animal (name) {
      this.name = name
    }
    var dog = new Animal('mender')
    console.log(dog)
    
    // 下面这个写法可以更方便的写原型方法
    Object.assign(Animal.prototype, {
      say () {
      },
      init () {
      }
    })

    console.log(Animal.prototype)
    // 原型上的constructor属性指向构造函数本身
    console.log(Animal.prototype.constructor === Animal) // true

    console.log(dog instanceof Animal) // true
    console.log(dog instanceof Object) // true
    console.log(dog instanceof Function) // false

    // instanceof用来判断数组
    var arr = [3,4,5]
    console.log(typeof dog) // object
    console.log(typeof arr) // object

    console.log(arr instanceof Array) // true
    console.log(dog instanceof Array) // false

    console.log(dog.hasOwnProperty('name')) // true
    console.log(dog.hasOwnProperty('say')) // false
    console.log(dog.hasOwnProperty('abc')) // false

    // 判断Animal的protytype在没在dog的原型链上
    console.log(Animal.prototype.isPrototypeOf(dog)) // true


    class Person {
      constructor (name) {
        this.name = name
      }
      say () {
        console.log(this.name)
      }
    }

    var xm = new Person('xiaoming')
    var xh = new Person('xiaohong')
    // class上写的方法默认在构造函数的原型上
    console.log(xm.say === xh.say) // true

this指向

// 1、全局this指window
    console.log(this) // window

    // 2、全局函数里的this指window
    function fn () {
      console.log(this) // window
    }
    fn()

    // 3、事件里的this指向当前事件绑定的DOM对象
    document.querySelector('#box').onclick = function () {
      console.log(this) // box
    }

    // 4、对象里的this指向当前对象本身
    var obj = {
      fn: function () {
        console.log(this) // obj
      }
    }
    obj.fn()

    // 5、构造函数里的this指将来实例化(new)出来的对象
    function Person () {
      console.log(this) // xm
    }
    var xm = new Person()

    // 6、原型方法里的this指将来new的对象
    Person.prototype.say = function () {
      console.log(this) // xm
    }
    xm.say()

    // 7、IIFE里的this指window
    ;(function () {
      console.log(this)
    })()

    // 8、只要没有说明归属的匿名函数的this指window
    setTimeout(function () {
      console.log(this)
    }, 1000)

    // 9、箭头函数没有自己的this
    const foo = () => {
      console.log(this) // window
    }
    foo()

    var obj2 = {
      fn: function () {
        setTimeout(function () {
          console.log(this) // window
        }, 1000)
      },
      fn2: function () {
        setTimeout(() => {
          console.log(this) // obj2
        }, 1000)
      }
    }
    obj2.fn()
    obj2.fn2()


    var a = 2
    function fun () {
      console.log(this.a)
    }
    var o = {a: 3, fun: fun}
    o.fun() // 3


    var p={ a: 4 }
    // 把赋值结果放入一个新的函数里在调用,this还是window
    ;(p.fun=o.fun)() // 2

    // 在面向对象程序里使用this
    // 1、this指当前对象用普通函数
    // 2、this指外层用箭头函数
    // 3、内外都需要,就在外层用_this存起来,this指内层, _this指外层

    // function fn () {
    //   const _this = this // 把外层this存起来了
    //   function foo () {
    //     this指向内层对象
    //     _this指向外层对象
    //   }
    // }
改变this指向

1、bind(this):将this指向外层
2、call() apply()都是在函数调用前修改this指向。区别在于后面的传参方式,如下

var a = 20
    var obj1 = {
      a: 10,
      fn: function (x, y) {
        console.log(this.a + x + y)
      },
      fn2: function () {
        // bind是在封装函数的时候直接把this修改为外层
        // ES6有了箭头函数,bind相对用的少了
        setTimeout(function () {
          console.log(this.a)
        }.bind(this), 1000)
      }
    }
    obj1.fn(1, 2) // 10

    // call和apply都是在函数调用之前修改this指向,区别在于传参
    // call的参数依次传递即可
    // apply需要传递一个数组
    obj1.fn.call(window, 1, 2) // 把fn里的this指向window
    obj1.fn.apply(window, [1, 2])
    obj1.fn2()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值