题目:
- this的不同应用场景,如何取值?
// 创建10个<a>标签,点击的时候弹出来对应的序号
let i, a
for (i = 0;i < 10; i++) {
a = document.createElement('a')
a.innerHTML = i + '<br>'
a.addEventListener('click',function (e) {
e.preventDefault()
alert(i)
})
document.body.appendChild(a)
}
- 作用域和自由变量
- 闭包
- this
作用域
代表了某个变量的合法范围
- 全局作用域
- 函数作用域
- 块级作用域(ES6新增)
// ES6 块级作用域
if (true) {
let x = 100
}
console.log(x) //会报错
自由变量
- 一个变量在当前作用域没有定义,但是被使用了
- 向上级作用域,一层一层依次寻找,直至找到为止
- 如果在全局作用域都没有找到,则报错xx is not defined
闭包
- 作用域应用的特殊情况,由两种表现:
- 函数作为参数被传递
- 函数作为返回值被返回
// 函数作为返回值
function create() {
let a = 100
return function () {
console.log(a) // 在这里定义,所以向上级进行查找
}
}
const fn = create()
const a = 200
fn(); //100
// 函数作为参数
function print(fn) {
const a = 200
fn()
}
const a = 100
function fn() {
console.log(a) // 在这里定义,所以向上级进行查找
}
print(fn) //100
闭包
自由变量的查找,是在函数定义的地方,向上级作用域查找,不是在执行的地方~~
this
- 作为普通函数 返回window
- 使用 call apply bind 传入什么就绑定什么
- 作为对象方法被调用 返回对象本身
- 在class方法中调用 实例本身
- 箭头函数 上级作用域
this是在函数执行的时候确认的,不是在定义的时候确定的
function fn1() {
console.log(this)
}
fn1() //window
fn1.call({ x: 100 }) //{x:100}
const fn2 = fn1.bind({ x: 200 })
fn2() //{ x: 200}
const zhangsan = {
name: '张三',
sayHi() {
//this 即当前对象
console.log(this)
},
wait() {
setTimeout(function(){
//this === window
console.log(this)
})
}
}
console.log(zhangsan)
const zhangsan = {
name: '张三',
sayHi() {
//this 即当前对象
console.log('this 即当前对象')
console.log(this)
},
wait() {
// 箭头函数 上级作用域
setTimeout(()=>{
//this 即当前对象
console.log(this)
})
}
}
console.log(zhangsan)
class People {
constructor(name) {
this.name = name
this.age = 20
}
sayHi() {
console.log(this)
}
}
const zhangsan = new People("张三")
zhangsan.sayHi() //zhangsan 对象
手写bind函数
Skip welcome & menu and move to editor
Textarea editor mode
JS Bin features
Getting started
Keyboard Shortcuts
Exporting/importing gist
Pro features
Private bins
Vanity URLs
Upgrade to pro now
Blog
The Return and The Refactor
Help
Delete a bin
Debbugging your preferences
Donate to JS Bin ❤
Support JS Bin to keep the project open source & MIT for all
Follow @js_bin on twitter
By using JS Bin you agree to our legal terms
// 模拟bind
Function.prototype.bind1 = function () {
// 将参数拆解为数组
const args = Array.prototype.slice.call(arguments)
// 获取this (数组第一项)
const t = args.shift()
// fn1.bind(...)中的fn1
const self = this
// 返回一个函数
return function () {
return self.apply(t,args)
}
}
function fn1(a,b,c){
console.log('this',this)
console.log(a,b,c)
return 'this is fn1'
}
const fn2 = fn1.bind1({x:100},10,20,30)
const res = fn2()
console.log(res)
//"this"
//[object Object] {
// x: 100
//}
//10
//20
//30
//"this is fn1"
实际开发中闭包的作用
- 隐藏数据
- 做一个简单的cache工具
// 闭包隐藏数据,只提供 API
function createCache () {
const data = {} //闭包中的数据,被隐藏,不被外界访问
return {
set: function (key,val){
data[key] = val
},
get: function (key) {
return data[key]
}
}
}
const c = createCache()
c.set('a',1000)
console.log(c.get('a'))
// 创建10个<a>标签,点击的时候弹出来对应的序号
let a
// 每一次都是不同的块作用域
for (let i = 0;i < 10; i++) {
a = document.createElement('a')
a.innerHTML = i + '<br>'
a.addEventListener('click',function (e) {
e.preventDefault()
alert(i)
})
document.body.appendChild(a)
}
小结
- 作用域和自由变量
- 闭包:两种常见形式&自由变量查找规则
- this