此篇文章,只是用来自己进行一个学习的总结,用于以后方便查看及复习。
一、JS原型对象
一、构造函数、原型、实例的关系:
1、构造函数:如果是通过new操作符调用的,那么就是构造函数,如果没有通过new操作符来调用的,就是普通函数。
2、每一个函数对象都有一个prototype属性,但是普通对象是没有的;prototype里面又有一个construetor又指向这个函数。
3、我们可以看到demo 是通过new操作符出来的,是一个构造函数,可以通过prototype找到它的原型。而qwe是一个普通函数,也是demo的实例,可以看到它的prototype是一个undefined
4、可以看到demo函数(对象)通过prototype找到了原型对象,里面有一个constructor,它又是指向 demo函数对象的。
二、原型链
实例对象与原型之间的连接,叫做原型链。__proto__隐式原型
JS在创建对象的时候,都有一个叫做__proto__的内置属性,用于指向创建它的函数对象的原型对象prototype。
内部原型__proto__和构造器的原型(prototype)
1、每个对象都有一个__proto__属性,原型链上的对象正是依靠这个属性连结在一起
2、作为一个对象,当你访问其中的一个属性或方法的时候,如果这个对象中没有这个方法或属性,那么Javascript引擎将会访问这个对象的__proto__属性进行向上查找,找到指向它的构造函数的显示原型prototype身上,并在那个对象中查找指定的方法或属性,如果不能找到,那就会继续通过那个对象 的__proto__属性指向的对象进行向上查找,直到返回为null。
三、this指向
function demo() {
console.log('demo ' + this); // 这个this指向Window
}
demo()
let fn2 = function () {
console.log('fn2 ' + this); // 此时的this也是指向Window
}
fn2()
let fn3 = function () {
'use strict' // 开启javascript 中的严格模式
console.log('fn3 ' + this); // 如果开启了严格模式,此时的this为undefined
}
fn3()
function fn4(exp) {
console.log(exp, this); // 此时的this 指向 arr 数组
}
var arr = [fn4, 1, 2]
arr[0]('arr')
let obj = {
a: 1,
b: function () {
console.log(this); // 此时的this 指向 obj
}
}
obj.b()
四、改变this指向
call()、apply()、bind()方法都是用来改变this指向的。其中call和apply 是可以改变this指向并且立即调用,bind改变this指向但是不立即调用,也可以给bind()后面再跟一个() 给它转换成立即调用。
1、改变this指向
可以看到通过改变call、apply、bind改变this指向,让原本fn中输出的this.age为 undefined的值 指向了 qwe 中的name和age。
bind返回的是一个新的函数,必须调用它才会被执行,所有后面添加一个()。
2、对比call、bind、apply传参
从上图可以看出:
call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象,第二个参数差别就来了:
call 的参数是直接放进去的,第二第三第 n 个参数全都用逗号分隔,直接放到后面 obj.fn.call(qwe,‘吃饭’, … ,‘string’ )。
apply 的所有参数都必须放在一个数组里面传进去 obj.fn.apply(qwe,[‘吃饭’, …, ‘string’ ])。
bind 除了返回是函数以外,它 的参数和 call 一样。
这三个函数传入的参数不限定是string类型,也允许是各种类型、包括函数、Object 等等。