美文网首页
JS 原型中的this理解

JS 原型中的this理解

作者: 流着万条永远的河 | 来源:发表于2017-11-06 16:17 被阅读0次

前面讲过了,在全局作用域下声明的函数或者变量,默认是window这个对象的属性了,前面再议函数时,说过,上下文这个概念跟作用域的概念的区别,上下文是一个目标变量被当成某个对象的属性或者方法时,这里的对象是目标的上下文,我是这么理解的。而this在代码层面上就是时刻指向这个对象了。

内部函数


这里的this怎么会这样呢?可以这样理解,要执行的是f0,所以f0是目标函数,这时候里面可以是这样的:

function f0(){
 // var this = window   这里隐含着一个这样的声明了。
  function f2(){
    console.log(this)
  }
  f2()
} 
f0()

setTimeout setInterval


document.addEventListener('click',function(e){
  console.log(this)
  setTimeout(function(){
    console.log(this)
  },200)
},false)

运行如图:



之前做项目封装的时候,在这个定时器上栽过很多跟头的,因为这个定时器是个独立的函数,不是跟内嵌的一样,因为它运行是异步运行在任务列表里的,我认为在任务队列里的时候它是全局作用域的变量,否则取消定时器不就只能放在它所在作用域里取消它了吗?那如何实时取消操作它呢?当然这里不能再说作用域了,比如这个是相对于变量的存在意义的范畴,而不是作为变量所属的对象研究的上下文。
这里老师给了一个一般性结论:
如果碰到了回调函数,那this基本都变了,否则也不会用回调函数了。

构造函数

上次写原型的时候,写new的作用,第一步就是创建一个空对象,空对象的proto等于原函数的prototype,第二部就是运行这个函数,运行时,函数里的this指向这个空对象,最后把加工了的空对象返回。

作为对象方法调用

var obj = {
  name:'haha',
  printname : function(){
  console.log(this.name)
}
}
obj.printname()  //'haha'

对象的方法调用,这个方法的对象就是这个对象了,this直接指向它喽。
陷阱:



fn是在全局声明的,就是window的属性了,只不过这个赋值的范畴让你迷惑,就是声明加赋值嘛。

DOM绑定事件

除了低版本的bug指向window,事件处理中的this代表事件源DOM对象。

document.addEventListener('click',function(e){
  console.log(this)
  var self = this              //经常用到的技巧,拿不准了,提前把this的指针赋值给一个变量,
//因为默认this这四个字母代表了当下目标变量的上下文,铁打的this,流水的变量。
  setTimeout(function(){
    console.log(this)
    console.log(self)
  },200)
},false)

Function.prototype.bind

bind返回一个新函数,并使函数内部的this为传入的第一个参数。
bind执行时,也就是返回的函数执行时,那个对象作为参数传了进来。换句话说,我们为这个函数设置了新对象。
所有的函数都是Function创造的,在Function.prototype.bind上加一个函数,所有的函数都有bind这个方法了。



它的作用有利于复用函数,而且是在指定的上下文里去运行。注意最后面的括号不要忘了,因为返回的是函数,要执行就要加。



再看看这样呢:
this.say是对的,this就是指的page,这时候,相当于事件被解读状态。但是触发事件运行事件的回调say函数时,里面的this就变了,代表了当前的事件事件节点。
验证一下;

var page = {
  init:function(){
    this.node = document.body
    this.bind()
  },
  bind:function(){
    this.node.addEventListener('click',this.say)
  },
  say:function(){
    console.log(this)
    console.log('haha')
  }
}

page.init()
结果;

那怎么办呢?


var page = {
  init:function(){
    this.node = document.body
    this.bind()
  },
  bind:function(){
    this.node.addEventListener('click',this.say.bind(this))
  },
  say:function(){
    console.log(this)
    console.log('haha')
  }
}

page.init()

那就对于上面那个DOM事件用bind处理一下吧:

document.addEventListener('click',function(e){
  console.log(this)
             
  setTimeout((function(){
    console.log(this)
  }).bind(this),200)
},false)

call ,apply设置this

fn.call(context,x,y,a,b,,,,)
fn.apply(contet,array)
//第一个参数是设置this的对象,剩下的是参数,一个是枚举形式,一个是数组形式。
function sum(){
  var result = 0
  var arg = Array.prototype.slice.call(arguments,0)
  var agu = Array.prototype.sort.call(arguments)
  var max = Math.max.apply(null,arg)       //之前讲过参数的传递,传少了会默认从第一个参数开始匹配,
//第一个是this的指向,必须要设,就设null,否则报错的
  Array.prototype.forEach.call(arguments,function(val){
    result += val
  })
  console.log(result,arg,agu,max)
  return result
  
}
sum(1,4,7,2)

就是简化我们的代码,一般call的处理速度更快。

caller

在函数A调用函数B时,被调用的B会自动生成一个caller属性,指向调用它的函数对象,如果没有被调用,或者并非被其他函数调用,caller= null。

function fn1(){
  console.log(fn1.caller)
  function fn2(){
    console.log(fn2.caller)
  }
  fn2()
}
fn1()

arguments

函数在调用时,传入的参数被加工生产出的一个类数组对象.


callee

当函数被调用时,它的arguments.callee对象会指向这个函数自身。对自己的引用,比如递归。
匿名函数特好用。



var i =1
window.onclick = function(){
  console.log(i)
  if(i<20){
    i++
    setTimeout(arguments.callee,3000)
  }
} //可以试试这个函数,相当于自己设定条件,只要满足了什么,
//它就可以无限调用自身的。可以做监察检测之类,判断状态,,,
//但是严格模式下用不了了,平时玩玩就可以了。

函数变量

  • 实例变量:this,类的实例才能访问到的
  • 静态变量:属性,直接类型对象能访问到的
  • 私有变量:局部变量,当前作用域内有效变量
function A(){
  var a =1      //局部变量
  this.b = 2    //实例变量,必须要创造实例
}
A.c = 3  //属性对象
console.log(a)     //error
console.log(A.b,A.c)   //undefined ,3
var d = new A()
console.log(a)    //error
console.log(d.b,d.c)  //2,undefined

this练习

函数调用的步骤认识

fn.call(context,x,y,,,,)  //任何函数调用都这样的,只不过大多数指向自身的设置为null。
fn(x,y)  === fn.call(undefined,x,y)
obj.child.mesold(x,y) ===obj.child.mesold.call(obj.child,x,y)
function fn(){
 console.log(this)
}
fn()  === fn.call(undefined)    
//如果传的是null,undefined,那么window默认是context,严格模式下写什么就是什么,没window的事儿。
var obj = {
  foo:function(){
    console.log(this)
  }
}
var bar  = obj.foo
obj.foo() === obj.foo.call(obj)  //foo前面是obj,那就是obj
bar()   === bar.call(null)    //bar前面没东西,那就是null
function fn(){
console.log(this)
}
var arr = [fn,fn2]
arr[0]()   ===arr.0.call(arr)

Event中的this

body.addEventListener('click',funcftion hand(){
  console.log(this)
})

this都是由call,apply指定的,要知道this指谁,就要看hand函数前缀是哪个,但是事件是内置的方法,看不了源码,MDN上说,当事件触发时,

hand.call(event.currentTarget,event)  //触发事件的作为this

,,,,

$ul.on('click','li',function(){
  console.log(this)
})      //Jquary?

文档中说的意思:this指向当前正在执行的事件的元素。对直接事件就是绑定的元素。对代理事件,就是当前触发事件的元素。

最后:
不要瞎猜,不清楚就console.log(this).

相关文章

  • 原型与新版的类-class

    首先来理解原型原型 === 共用属性可以先看看方姐的几篇文章:什么是JS原型链JS 中 proto 和 proto...

  • JS 原型中的this理解

    前面讲过了,在全局作用域下声明的函数或者变量,默认是window这个对象的属性了,前面再议函数时,说过,上下文这个...

  • 理解JS中的原型

    动态语言和静态语言有很大的不同,比如在C++中定义类时,并不分配内存,而在动态语言中定义类时,却会分配内存。 比如...

  • 廖雪峰JS小记

    (function(){})() 原型,原型链 浅谈Js原型的理解JS 原型与原型链终极详解 对象 对象:一种无序...

  • js new 运行机制

    js手札--js中new到底做了些啥JS核心系列:理解 new 的运行机制深入理解 Javascript 运行机制及原型

  • 原型

    一:你是如何理解js 中的原型的 1.原型是什么? 我们js中 所有的的函数 包括原生的,和自定的 都默认有一个 ...

  • js中难以理解的原型

    原型;我们先来看段简单的函数 按照javascript的说法,function定义的这个Person就是一个Obj...

  • JS中函数原型的理解

    函数原型 函数有一个默认的prototype属性, 默认值是只有一个属性constructor的对象函数只是有一个...

  • JS原型

    最近一直在理解JS的原型------《你不知道的JS》--------《JS设计模式》 里面都讲JS的原型运作方式...

  • 前端资料

    ES6新数据类型 Symbol . js变量提升函数提升 js this js 原型及原型链理解 new做了什么 ...

网友评论

      本文标题:JS 原型中的this理解

      本文链接:https://www.haomeiwen.com/subject/upbkmxtx.html