文/小魔女
本文简介
-
前端开发必会的JS硬知识的第二篇文
-
Javascript是前端必不可少的,它涵盖的内容很多。
-
本系列将把前端开发得掌握的所有知识点整理并分享给大家,本文将围绕this、原型链与继承展开。
-
分享小魔女的音乐🎵
this
this是Javascript语言的一个关键字。 随着函数使用场合的不同,this的值会发生变化。但是有一个总的原则,谁调用,this就指向谁。
this的指向(4种)
-
在全局作用域或者普通函数中,this指向全局对象window
2.方法调用中,谁调用指向谁
3.在构造函数或者构造函数原型对象中,this指向构造函数的实例
es6中的箭头函数与普通函数有什么区别?
-
普通函数this指向调用者,箭头函数的this指向定义的环境(bind\call\apply都不能改变this的指向)
-
箭头函数没有arguments,没有函数体,需要使用...rest代替
-
箭头函数不能作为构造函数,不能new
-
箭头函数不能使用yield命令,不能作为generator函数
-
箭头函数没有原型属性
-
变量提升:在js的内存机制里,function的级别最高。而箭头函数定义函数是,需要var、let、const等关键字,而只有var能进行变量提升,所以箭头函数定义一定要在调用之前
bind、call和apply有什么区别?
-
同:bind、call和apply的第一个参数都是this
-
异:
-
call,传参方式是列举
-
apply,传参方式是数组
-
重点: call,apply会指向函数(调用),而bind只会改变this,不会指向函数(会返回函数)
-
练兵场
实现bind
什么是原型对象?什么是原型链?
-
原型对象:
-
所有引用类型都有一个__proto__(隐式原型)属性,属性值是一个普通的对象
-
所有函数都有一个prototype(原型)属性,属性值是一个普通的对象
-
所有引用类型的__proto__属性都指向它构造函数的prototype
-
-
原型链:
-
当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即是构造函数的prototype,如果还没有找到就会在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们成为原型链。
-
一直往上查找,直到到null还没有找到,则返回undefined
-
Object.prototype.**proto** === null
-
所有从原型或更高级原型中得到、执行的方法,其中的this在执行时,执行当前这个触发事件的执行对象。
-
如何通过一个实例访问它的构造函数及原型对象?
注:通过class定义的类 和通过构造函数定义的类 二者本质相同。并且在js执行时,会将第一种转会为第二种执行。所以 ES6 class的写法实质就是构造函数。
-
实例访问构造函数:example.constructor
-
实例访问原型对象:example.**proto**
请实现Cat继承Animal的属性,并比较各继承的优缺点
原型链继承
-
优点:实例是父类的实例,也是子类的实例。父类新增在原型上的方法和属性,所有子类都可以访问到。简单 易于实现
-
缺点:无法实现多继承。来自原型对象的引用属性和实例,所有子类都是共享的。创建子类实例时,无法向父类构造器传参。(可以在构造函数中,为实例增加实例属性。)
// 原型链继承 function Animal() { this.species = "动物" }
function Cat(name, color) { this.name = name this.color = color }
// 核心:父类的实例作为子类的原型 Cat.prototype = new Animal()
构造继承
-
相当于复制父类的属性方法给子类(没有用到原型)
-
子类不能访问父类原型上的方法和属性
function Animal() {
this.species = "动物";
}function Cat(name, color) {
this.name = name;
this.color = color;//方法1: Animal.call(this)
//方法2: Anmial.apply(this) }
组合继承
function Animal() {
this.species = "动物"
}
function Cat(name, color) {
this.name = name
this.color = color
}
Cat.prototype= new Animal()
Cat.prototype.constructor = Cat //修复构造函数的指向
寄生组合继承 (最好)
function Animal() {
this.species = "动物"
}
function Cat(name, color) {
Animal.call(this)
this.name = name
this.color = color
}
function F(){}
F.prototype= Animal.prototype
Cat.prototype= new F()
Cat.prototype.contructor = Cat
new一个实例,经历了什么过程?
自己写一个new方法
es6中的static的作用是什么?用es5如何实现?
类就是实例的原型。class就是构造函数。在方法前加上static关键字,该方法不会被实例继承,只能直接通过类来调用,也就是静态方法.
举个🌰:
那父类静态方法,子类如何继承?
使用extend关键字
用es5如何实现?
使用构造继承
JS单线程是怎么运作的?请说下“异步”和“同步”的区别
-
js单线程要分为浏览器和node环境
-
浏览器环境:
-
先执行同步代码
-
执行异步代码的所有微任务
-
执行异步代码的一个宏任务
-
执行执行异步代码的所有微任务 5.执行异步代码的一个宏任务 6.循环
-
-
node环境
-
先执行同步代码
-
执行异步代码的所有微任务
-
执行异步代码的所有宏任务
-
执行执行异步代码的所有微任务
-
执行异步代码的所有宏任务
-
循环
-
-
node的宏任务有六个任务队列
-
浏览器的宏任务都在同一个任务队列
练兵场
处理异步任务的方法有哪些?
-
回调函数 (回调不一定是异步 使用这个实现)
function f1(callback) { setTimeout(function() { callback() }, 1000) } function f2(){} f1(f2)
-
事件监听(事件驱动模式)on,bind,listen,addEventListener,observe
function f1() { setTimeout(function(){ f1.trigger('done') },1000) }
f1.on('done',f2)
-
优:易于理解、可绑定多个事件,可以去耦合,利于模块化。
-
缺:整个程序变成事件驱动型,运行流程不清晰。
-
发布/订阅(publish/subscribe)
JQuery.subscribe('done', f2) //订阅done function f1() { setTimeout(function() { jQuery.publish('done') //执行f1任务代码 }, 1000) } JQuery.unsubscribe('done', f2) //执行后取消订阅
-
Promise对象
-
async/await
请实现一个同步的delay方法
魔女有话说
很感谢你能看到这里,希望你能够有所收获。在学习的路上,大多都是艰辛的,但是只要我们有所期待,坚持不放弃,总会成功的。我们一定要看到成功人士背后的艰辛。今天的知识点都是作为一个前端必须要掌握的,如果读的时候,感觉有点吃力,不妨收藏下来,多读几次。我也会坚持输出高质量的文章,不愿辜负粉丝。 如果可以,请给我点在看,并关注公众号。你的支持,是我坚持的动力。谢谢~~