函数是一种可执行代码组成的对象
var obj = {
name: 'frank',
length: 2,
params: ['x', 'y'],
functionBody: 'console.log('hello world')',
}
objGongYong = {
call: function(x) {
eval(x.functionBody)
}
}
obj.__proto__ = objGongYong
obj.call(obj) // 'hello world'
所谓函数, 就是一个对象, 里面的某个属性存储了一段可用eval 执行的字符串. 函数只是存在于内存中的一段字符串而已, 如果某个对象的属性是一个函数, 这个属性本身并不是函数, 而是存储了引用这个函数的内存地址而已
有关函数的三段论:
- 参数的值只有在传参的时候确定
- this 是第一个参数( call)
=> this的值只有在传参的时候确定
看看下面几个面试题
function a() {
console.log(this) // 不确定打印出什么, 因为调用函数时不一定传的什么参数
}
a() // 在浏览器里执行,里面的 this 是 window
a() // 在 nodejs 中执行, this 是 global
function a() {
'use strict'
console.log(this)
}
a() // undefined
var obj = {
sayThis: a
}
obj.sayThis() //obj这个对象
obj.sayThis.call() // undefined
obj.sayThis.call(1) // 1
obj.sayThis.call(2) // 2
//下面是一些比较特殊的情况, 我们无法直接判定 this 是什么, 根据文档可以知道 this 代表什么, 但是我们仍可以利用 call 方法自己制定 this是什么
//这个函数调用时传递的第一个参数到底是什么? Button, 这是由浏览器保证的, 在MDN 写到: 句柄里的 this 值触发事件的元素
button.onclick = function() {
console.log(this)
}
// 用 jquery 的时候, 文档里也说明this 是调用方, 即是 button(this关键字指向当前正在执行的时间元素)
$('#button1').on('click', function() {
console.log(this)
})
// 对于代理事件而言, this 则代表了与 selector 相匹配的元素
// 这里的 this 为 li, 而不是 ul
$('ul').on('click', 'li', function() {
console.log(this)
})
由于 this 的用法不是很友好, 现在 JS 当中引入了箭头函数, 箭头函数中的 this 不再受传参的影响, 外面的 this 是什么, 里面是的 this 就是什么.
总结一下, this 的值不要轻易的平第一感觉去确定, this 就是一种参数的写法, 在传参不确定的情况下, 就无法确定 this 是什么. 另外建议就是尽量少用 this.