农历2019即将过去,趁着年前几天上班事情少,整理了一下javascript的基础知识,在此给你们作下分享,喜欢的大佬们能够给个小赞。本文在github也作了收录。javascript
本人github: github.com/Michael-lzg前端
使用 JavaScript 开发的时候,不少开发者多多少少会被 this 的指向搞蒙圈,可是实际上,关于 this 的指向,记住最核心的一句话:哪一个对象调用函数,函数里面的 this 指向哪一个对象。vue
全局变量指向全局对象-windowjava
var username = 'cn'
function fn() {
alert(this.username) //cn
}
fu()
复制代码
有一点须要注意,let 声明的全局变量,不是指向 window 对象webpack
let username = 'cn'
function fn() {
alert(this.username) //undefined
}
fn()
复制代码
就是那个函数调用,this 指向哪里git
window.b = 2222
let obj = {
a: 111,
fn: function() {
alert(this.a) //111
alert(this.b) //undefined
}
}
obj.fn()
复制代码
JS里的普通函数可使用new操做符来建立一个对象,此时该函数就是一个构造函数,箭头函数不能做为构造函数。执行new操做符,其实JS内部完成了如下事情:github
function A () {
this.a = 1
this.func = () => {
return this
}
}
let obj = new A()
console.log(obj.a) // 1
console.log(obj.func() === obj) // true
复制代码
箭头函数的this指向,和箭头函数定义所在上下文的this相同。对于普通函数,this在函数调用时才肯定;而对于箭头函数,this在箭头函数定义时就已经肯定了,而且不能再被修改。web
let obj = {
A () {
return () => {
return this
}
},
B () {
return function () {
return this
}
}
}
let func = obj.A()
console.log(func() === obj) // true
func = obj.B()
console.log(func() === obj) // false
console.log(func() === window) // true
复制代码
在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向。 举个例子算法
function fruits() {}
fruits.prototype = {
color: 'red',
say: function() {
console.log('My color is ' + this.color)
}
}
var apple = new fruits()
apple.say() //My color is red
// 可是若是咱们有一个对象banana= {color : "yellow"} ,咱们不想对它从新定义 say 方法,
//那么咱们能够经过 call 或 apply 用 apple 的 say 方法:
banana = {
color: 'yellow'
}
apple.say.call(banana) //My color is yellow
apple.say.apply(banana) //My color is yellow
复制代码
对于 apply、call 两者而言,做用彻底同样,只是接受参数的方式不太同样vue-cli
func.call(this, arg1, arg2)
func.apply(this, [arg1, arg2])
复制代码
apply、call 实例
// 数组追加
var array1 = [12 , "foo" , {name:"Joe"} , -2458];
var array2 = ["Doe" , 555 , 100];
Array.prototype.push.apply(array1, array2);
// array1 值为 [12 , "foo" , {name:"Joe"} , -2458 , "Doe" , 555 , 100]
// 获取数组中的最大值和最小值
var numbers = [5, 458 , 120 , -215 ];
var maxInNumbers = Math.max.apply(Math, numbers), //458
var maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458
// 验证是不是数组
functionisArray(obj){
return Object.prototype.toString.call(obj) === '[object Array]'
}
复制代码
bind()最简单的用法是建立一个函数,使这个函数不论怎么调用都有一样的 this 值。 bind()方法会建立一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以建立它时传入 bind()方法的第一个参数做为 this,传入 bind() 方法的第二个以及之后的参数加上绑定函数运行时自己的参数按照顺序做为原函数的参数来调用原函数。
this.num = 9
var mymodule = {
num: 81,
getNum: function() {
console.log(this.num)
}
}
mymodule.getNum() // 81
var getNum = mymodule.getNum
getNum() // 9, 由于在这个例子中,"this"指向全局对象
var boundGetNum = getNum.bind(mymodule)
boundGetNum() // 81
复制代码
当调用 bind 函数后,bind 函数的第一个参数就是原函数做用域中 this 指向的值
function func() {
console.log(this)
}
let newFunc = func.bind({ a: 1 })
newFunc() // 打印:{a:1}
let newFunc2 = func.bind([1, 2, 3])
newFunc2() // 打印:[1,2,3]
let newFunc3 = func.bind(1)
newFunc3() // 打印:Number:{1}
let newFunc4 = func.bind(undefined / null)
newFunc4() // 打印:window
复制代码
传递的参数的顺序问题
function func(a, b, c) {
console.log(a, b, c) // 打印传入的实参
}
let newFunc = func.bind({}, 1, 2)
newFunc(3) //1,2,3
// 能够看到,在 bind 中传递的参数要先传入到原函数中。
复制代码
返回的新函数被当成构造函数
// 原函数
function func(name) {
console.log(this) // 打印:经过{name:'wy'}
this.name = name
}
func.prototype.hello = function() {
console.log(this.name)
}
let obj = { a: 1 }
// 调用bind,返回新函数
let newFunc = func.bind(obj)
// 把新函数做为构造函数,建立实例
let o = new newFunc('seven')
console.log(o.hello()) // 打印:'seven'
console.log(obj) // 打印:{a:1}
复制代码
新函数被当成了构造函数,原函数 func 中的 this 再也不指向传入给 bind 的第一个参数,而是指向用 new 建立的实例。在经过实例 o 找原型上的方法 hello 时,可以找到原函数 func 原型上的方法。
var obj = {
x: 81
}
var foo = {
getX: function() {
return this.x
}
}
console.log(foo.getX.bind(obj)()) //81
console.log(foo.getX.call(obj)) //81
console.log(foo.getX.apply(obj)) //81
复制代码
关注的个人公众号不按期分享前端知识,与您一块儿进步!