构造函数原型prototype,每一个构造函数都有一个原型对象,我们可以把那些不变的方法 直接定义再prototype对象上,这样所有的实例就可以共享这些方法
1.原型是什么:是一个对象,prototype对象 2.原型的作用是:共享方法,公共属性定义到构造函数里,公共的方法定义到原型对象上节约内存
- function Star(name) {
- this.name = name
- }
- Star.prototype.sing = function () { //一般情况,我们的公共属性定义到构造函数里,公共的方法定义到原型对象上节约内存
- console.log('唱歌');
- }
- let ldh = new Star('刘德华')
- ldh.sing()
- let zxy = new Star('张学友')
- zxy.sing()
- console.dir(Star)// 有prototype
- console.log(ldh.sing === zxy.sing) // true
- // 为什么ldh实例能调用Star构造函数中的sing方法 因为ldh这个对象上有一个隐式原型__proto__指向的是我们的构造函数
- console.dir(ldh); // 对象身上系统自动添加了__proto__指向的是我们的构造函数的prototype
- console.log(ldh.__proto__ === Star.prototype) // true ,方法的查找如果lad对象上有sing就执行,如果ldh没有sing就去构造函数的prototype上查找,因为__proto__指向prototype
- console.log(ldh.__proto__) // 有constructor这个属性
- console.log(Star.prototype) // 有constructor这个属性
- console.log(ldh.__proto__.constructor) //指向的是Star
- console.log(Star.prototype.constructor) //指向的是Star
- // 很多情况下我们要手动修改constructor的指向,比如我们要定义多个方法sing movie
- Star.prototype = {
- constructor: Star, // 手动指向
- sing: function () {
- console.log('唱歌');
- },
- movie: function () {
- console.log('电影');
- }
- }
- console.log(Star.prototype.constructor) *// 指向的是Object,因为赋值的是一个对象导致constructor对覆盖了,故需要手动指向
1.原型对象中的this指向实例对象
- function Star(name) {
- this.name = name
- }
- var that
- Star.prototype.sing = function () {
- console.log('唱歌');
- that = this
- }
- let ldh = new Star('刘德华')
- ldh.sing()
- console.log(that === ldh)
2.函数中this指向
- function run() {
- console.log(this);
- }
- window.run() // 完整的写法是这样的,window是调用者,普通函数this指向window
- var o = {
- say() {
- console.log(this);
- }
- }
- o.say() //对象方法this 指向的是o这个对象,因为是o调用的
- function Start() {
- start.prototype.eat = function(){}
- }
- var ldh = new Start() // 构造函数的this 指向实例对象ldh ,原型对象里面的this 也指向ldh这个实例对象
- btn.onclik = function(){
- console.log(this);
- } // 绑定事件的函数的this 指向btn这个实例
- window.setTimeout(()=>{},1000) // this指向window
- (function(){console.log(1);})() // 立即执行函数 this指向window
1.call()
call(thisArg,arg1,arg2,...), call 呼叫的意思很直接
fun.call(thisArg,arg1,arg2,...) //第一个参数是把this指向谁,后面的是其他类型参数
call的作用 1是调用函数 2是改变this指向
call主要作用是实现继承 在es5的时候
- function run(a,b) {
- console.log(this);
- console.log(a+b);
- }
- var o = {
- name: 'zhangsan'
- }
-
- // run.call() // 这样也能调用函数,没有修改this指向
- // run.call(o) // 改变this指向为o
- run.call(o,1,2) // 3
-
-
- function Father(name, age) {
- this.name = name,
- this.age = age
- }
- function Son(name, age) {
- Father.call(this,name,age) //修改this指向为Son
- }
-
- var son = new Son('ldh',18)
- console.log(son); // Son {name: "ldh", age: 18}
2.apply()
apply(thisArg,[argsArg]),apply字面意思是应用 ,也是很直接的
fun.apply(thisArg,[argsArg]) //第一个参数是把this指向谁,后面必须写成数组
apply的作用 1是调用函数 2是改变this指向
apply主要作用是跟数组 对数组求最大值,数组本身没有求最大值得方法,但是Math有,我们通过apply改变下指向为apply
- function run() {
- console.log(this);
- console.log(arguments); // 12 'pink',如果数组中传入的是number,输出的也是数字型,如果传入的是str那么输出的也会是字符串
- }
- var o = {
- name: 'zhangsan'
- }
-
- // run.apply() // 也能调用函数
- // run.apply(o) //改变this指向为o
- run.apply(o,[12,'pink'])
-
- var arr = [1,543,47,8,686,3]
- var max = Math.max.apply(Math,arr) // 改变this指向为Math ,然后第二个参数需传入数组
- console.log(max);
3.bind() 是重点掌握的!!!!
bind(thisArg,arg1,arg2,...), bind字面意思是绑定 捆绑的意思
fun.bind(thisArg,arg1,arg2,...) //第一个参数是把this指向谁,后面其他参数类型
bind的作用 1不会不会不会调用函数 2 是改变this指向 3,会返回一个新的函数
主要作用是 不需要立即执行的时候我们就需要想到bind这是我们最常用的方式 如一个按钮点击的时候就禁用,三秒之后才会启动
- function run (a,b) {
- console.log(this);
- console.log(a + b);
- }
- let p = {
- name: 'zhangsan'
- }
- let f = run.bind(p) // 只是改变this指向,不会调用函数
- f() //会返回一个新的函数,并以这样的形式调用函数
-
- let f2 = run.bind(p,1,2)
- f2()
-
- // 经典
- <button>点击</button>
- <button class="btn">点击1</button>
- <button class="btn">点击2</button>
- <button class="btn">点击3</button>
-
- var btn = document.querySelector('button')
- btn.onclick = function() {
- this.disabled = true // 点击后禁用
- // setTimeout(()=>{ // 操 这里是箭头函数无this指向,指向的是上级的this ,上级就是btn实例
- // // btn.disabled = false
- // this.disabled = false
- // },2000)
- setTimeout(function(){
- // btn.disabled = false // 这样有很多弊端,一旦按钮多一百个之后 ,显然这样写不科学
- // this.disabled = false // 此时这里的this,是指向的是window ,启用无效
- this.disabled = false
- }.bind(this),2000) // 我们需要的是不立即执行,但是需要改变的是this指向,故采用bind,我们这里的bind是写在定时器函数的外部,在btn函数内部,故bind(this)这里的this 指的是当前点击的按钮实例
- }
-
-
- // 点击多个按钮,实现禁用启用
- var btn1 = document.querySelectorAll('.btn')
- var len = btn1.length // 类似做过dom查询做缓存
- for(let i = 0;i<len;i++) {
- btn1[i].onclick = function() {
- this.disabled = true
- setTimeout(function(){
- this.disabled = false
- }.bind(this),2000)
- }
- }