原型和原型链
JS是基于原型的语言,ES6之前只能通过原型来继承,之后可以用class来继承,虽然class的基础也是原型,它相当于一个模板
class 是ES6 语法规范,有ECMA 委员会发布
ECMA只规定了语法规则,即我们代码的书写规范,不规定如何实现
文章目录
一、如何准确判断一个变量是不是数组
knowledge point:
用instanceof
answer:
a instanceof Array
二、手写一个简易的jQuery , 考虑插件和扩展性
knowledge point:
通过写jQuery来,理解原型链和原型
answer:
<p>一段文字 1</p>
<p>一段文字 2</p>
<p>一段文字 3</p>
1、jQuery原型
class jQuery {
constructor(selector) {
const result = document.querySelectorAll(selector) //这个是DOM查询
const length = result.length
for (let i = 0; i < length; i++) {
this[i] = result[i]
}
this.length = length
this.selector = selector
//类似于数组,但它确实是一个对象
}
get(index) {
return this[index]
//返回第几个DOM元素
}
each(fn) {
//each的时候会传入一个函数
//遍历
for (let i = 0; i < this.length; i++) {
const elem = this[i]
fn(elem)
}
}
on(type, fn) {
//监听一个方法
return this.each(elem => {
elem.addEventListener(type, fn, false)
})
}
// 扩展很多 DOM API
}
通过p标签来查询所以的DOM元素:
调用each()打印元素的标签名,
on()点击弹出警告框,内容为clicked
2、jQuery的扩展和插件
jQuery的插件就是直接在jQuery的显示原型里面添加函数
复写机制:
就是用这个不再用jQuery
这个要用extends
插件机制
还是要用jQuery,才能调用这个函数
class jQuery {
//、、、、
}
// 插件机制
jQuery.prototype.dialog = function (info) {
alert(info)
}
// 复写机制 ===> “造轮子”
class myJQuery extends jQuery {
constructor(selector) {
super(selector)
}
// 扩展自己的方法
addClass(className) {
console.log('hhhhhh')
}
style(data) {
}
}
// const $p = new jQuery('p')
// $p.get(1)
// $p.each((elem) => console.log(elem.nodeName))
// $p.on('click', () => alert('clicked'))
$p.dialog ('abc')
const $a = new myJQuery('p')
$a.addClass('abc') //'hhhhhh'
三、class的原型本质,怎么理解?
knowledge point:
- 原型和原型链的图示
- 属性和方法的执行规则,是怎么通过原型链找的
四、class和继承(knowledge point)
1、class
class以大写字母开头
1. constructor
2. 属性
3. 方法
// 类
class Student {
constructor(name, number) {
this.name = name
this.number = number
// this.gender = 'male'
}
sayHi() {
console.log(
`姓名 ${this.name} ,学号 ${this.number}`
)
//上面是用了``,相当于下面不使用``的一样
// console.log(
// '姓名 ' + this.name + ' ,学号 ' + this.number
// )
}
// study() {
// }
}
// 通过类 new 声明一个 对象/实例
const xialuo = new Student('夏洛', 100)
console.log(xialuo.name)
console.log(xialuo.number)
xialuo.sayHi()
const madongmei = new Student('马冬梅', 101)
console.log(madongmei.name)
console.log(madongmei.number)
madongmei.sayHi()
注释
- this: 表示当前正在构造的实例
- ` ` : 表示在里面输入的内容中可以用${},把变量写进去,然后变量的值就会输出
- 属性: name、number
- 方法: sayHi()
2、继承
- extends
- supper
- 扩展或重写方法
// 父类
class People {
constructor(name) {
this.name = name
}
eat() {
console.log(`${this.name} eat something`)
}
}
// 子类
/**
* 继承了父类的name属性还有eat方法
* 自己实现了sayHi方法和number属性
*/
class Student extends People {
constructor(name, number) {
super(name)
this.number = number
}
sayHi() {
console.log(`姓名 ${this.name} 学号 ${this.number}`)
}
}
// 子类
class Teacher extends People {
constructor(name, major) {
super(name)
this.major = major
}
teach() {
console.log(`${this.name} 教授 ${this.major}`)
}
}
// 学生的 实例
const xialuo = new Student('夏洛', 100)
console.log(xialuo.name)
console.log(xialuo.number)
xialuo.sayHi()
xialuo.eat()
// 老师的 实例
const wanglaoshi = new Teacher('王老师', '语文')
console.log(wanglaoshi.name)
console.log(wanglaoshi.major)
wanglaoshi.teach()
wanglaoshi.eat()
注释
五、类型判断instanceof(knowledge point)
Object是所有class的父类,但是当一个class有继承的父类时,该class的直接父类不是Object
eg:Student的父类是People,而Object是Student的祖先,即父类的父类
xialuo instanceof Student //true xialuo是由Student这个class构造出来的
xialuo instanceof People //true People是Student的父类,所以People也参与xialuo 的构造
xialuo instanceof Object //true
[] instanceof Array //true
[] instanceof Object //true
{} instanceof Object //true {}表示对象
instanceof 就是通过原型链一层一层往上找,看看能不能找到对应的显示原型
xialuo instanceof Student 就是从xialuo的隐式原型中向上找,看看能不能找到Student的显示原型,找到则true,否则false
六、原型和原型链(knowledge point)
1、原型
- 每个class都有显示原型 prototype
- 每个实例都有隐式原型__proto__
- 实例的__proto__都指向对应的class的prototype
获取属性 xialuo.name或xialuo.sayHi()时:
- 先在自身属性和方法寻找
- 如果找不到则自动去__proto__中查找
//class 实际上是函数,可见是语法糖
typeof People //'function'
typeof Student //'function'
//隐式原型和显示原型
console.log( xialuo.__proto__) //隐式原型
console.log( Student.prototype) //显示原型
console.log( xialuo.__proto__=== Student.prototype) //true
注释
- undefined:出现undefined是由于作用域的关系
- Student:当student这个类声明之后,是通过Student.prototype才能获取sayHi()
- xiaoluo:是通过类来了new一个,才声明的实例
- xialuo.sayHi():是需要通过xialuo.__proto__才能获取的
- xialuo.name和xialuo.number : 是直接放在xialuo这个实例中的,直接在自身中即可找到
2、原型链
console.log( Student.prototype.__proto__)
console.log( People.prototype)
console.log( People.prototype === Student.prototype.__proto__)
验证
通过xxx.hasOwnProperty()来判断是否为xxx拥有的自己属性