1.面向对象:是一种注重结果的思维方式
2.面向对象三大特征: 封装 、 继承 、 多态
(1).封装 : 把代码放入对象的方法中
(2)继承 : 一个对象 拥有 另一个对象 所有的成员
(3)多态 : 一个对象 在不同情况下的不同状态(* js语言基本不涉及多态)
继承:一个对象 拥有另一个对象的所有成员
原形继承:吧父对象 作为子对象构造函数的原形
例子:
//父对象
let father = {
house:{
address : '深圳湾一号',
price: 20000000
},
car:{
brand : '劳斯莱斯幻影',
price:15000000
}
}
//子对象
//构造函数
function Son(name,age){
this.name = name
this.age = age
}
//原型继承: 把父对象 作为子对象构造函数的原型
Son.prototype = father
//可选 : 原型继承之后,由于父对象覆盖原来的 子对象构造函数原型, 就会导致constructor消失.
//解决办法: 手动添加。(对开发几乎没有影响,也可以不加)
Son.prototype.constructor = Son
//实例对象
let s1 = new Son('ikun',30)
let s2 = new Son('班长',20)
console.log(s1,s2)
原形链:
1.原型链 : 每一个对象都有自己的原型, 而原型也是对象,也会有自己的原型,此次类推形成链式结构。称之为原型链。(原型链的终点是null)
2.对象访问原型链规则 : 就近原则
* 对象先访问自己的,自己没有就找原型的,原型没有就找原型的原型,一直到原型链终点null.如果还找不到。 属性则获取undefined, 方法则会报错 xxx is not function
3.经典面试题
(1)原形链作用 : 继承
(2)js如何实现面向对象继承:原形链
原形链流程图
所有构造函数都是Function的实例,所有原型对象都是Object的实例除了Object.prototype
内置对象原型链
// 数组对象
//实例化对象
let arr = [10,20,30]//new Array(10,20,30)
console.log( arr )
//1.1 查看arr的原型
console.log( arr.__proto__.constructor )//Array
console.log( arr.__proto__ === Array.prototype )//true
//1.2 查看arr的原型的原型
console.log( arr.__proto__.__proto__.constructor )//Object
console.log( arr.__proto__.__proto__ === Object.prototype )//true
// 字符串对象
let str = new String('abc')
console.log( str )
//2.1 查看str的原型
console.log( str.__proto__.constructor )//String
console.log( str.__proto__ === String.prototype )//true
//2.2 查看arr的原型的原型
console.log( str.__proto__.__proto__.constructor )//Object
console.log( str.__proto__.__proto__ === Object.prototype )//true
// 日期对象
let date = new Date()
/* js有几个特殊的对象 无法使用 log来打印的,需要用dir来打印: function date dom对象 */
console.dir( date )
//3.1 查看date的原型
console.log( date.__proto__.constructor )//Date
console.log( date.__proto__ === Date.prototype )//true
//3.2 查看date的原型的原型
console.log( date.__proto__.__proto__.constructor )//Object
console.log( date.__proto__.__proto__ === Object.prototype )//true
DOM对象原型链
1. instanceof(关键字): 运算符
用于检测 构造函数的prototype在不在实例对象的原型链中(说人话: 亲子鉴定,鉴定两个对象之间有没有血缘关系)
2. 写法:实例对象 instanceof 构造函数
instanceof原理: (面试题)
检测 右边构造函数的prototype 在不在 左边实例对象的原型链中
3. 应用 : 某些函数为了限制你的数据类型,在内部需要用instanceof进行判断是否是正确的数据类型
例子:
let arr = [10,20,30]
// arr-> Array.prototype -> Object.prototype -> null
console.log( arr instanceof Array )//true
console.log( arr instanceof Object )//true
console.log( arr instanceof String )//false
//封装一个函数,要求这个函数必须要传数组类型、 传其他类型不可以
function fn(arr){
if( arr instanceof Array){
console.log( arr.reverse() )
}else{
console.log('数据类型错误')
}
}
fn( [10,20,30] )
fn( 'abc' )
原型链应用:封装提示框案例
<script>
// 构造函数
function Modal(title, url) {
this.title = title
this.url = url
this.modalBox = `
<div class="modal">
<div class="header">${title} <i>x</i></div>
<div class="footer">
<img src="${url}" alt="" width="100%">
</div>
</div>
`
}
// 对象
Modal.prototype.open=function(){
// 创建div
let div = document.createElement('div')
// 设置标签内容
div.innerHTML = this.modalBox
// 添加到页面
document.body.appendChild(div)
// 给关闭按钮注册事件
div.querySelector('.modal i').addEventListener('click',function(){
div.remove()
})
}
// 实例对象
document.querySelector('#btn1').addEventListener('click',function(){
let m1 = new Modal('提示信息', './111.jpg')
m1.open()
console.log(m1)
})
document.querySelector('#btn2').addEventListener('click',function(){
let m2 = new Modal('提示信息', './222.jpg')
m2.open()
})
document.querySelector('#btn3').addEventListener('click',function(){
let m3 = new Modal('提示信息', './333.jpg')
m3.open()
})
</script>
函数补充
1: arguments关键字: 获取函数所有的 实参,是一个伪数组 : 有数组三要素(元素、下标、长度),但是不能使用数组的方法。
(1)应用 : 一般用户参数数量不限的函数.
(2)例如: arr.push() Math.max() 这些函数实参数量不限,底层原理就是使用arguments来接收所有的实参
2: 剩余参数(rest参数) : 获取函数剩余的所有实参
(1)语法: function 函数名(形参1,...形参2){}
(2) rest参数是真数组
(3)注意点:剩余参数必须写在最后一个形参位置
3:rest参数在一般情况下,可以替代arguments
4: 函数默认参数:function 函数名(形参=默认值){ }
例子:
function fn(a=10,b=20){ //实参有数据则是实惨的数据 实参没有数据则是=后面的数据
console.log(a) //5
console.log(b) //20
console.log(a+b) //25
}
fn(5)
for-in与for-of区别(面试题)
1.功能不同
for-in是遍历数组的下标
for-of是遍历数组的元素
2.原型的属性
for-in会遍历原型的属性
for-of不会遍历原型的属性
3.数据类型
for-in可以遍历Object类型
for-of不可以遍历Object类型
总结:如果只想要属性值/元素,使用for-of效率更高
例子:
let arr = [10,20,30]
console.log(arr)
//给数组原型添加属性
Array.prototype.age = 66
let obj = {
name:'张三',
age:20,
sex:'男'
}
//1.for-in循环
for(let key in arr){
console.log( key )//下标
console.log( arr[key] )//元素
}
//2. for-of循环
for(let item of obj ){
console.log( item )//元素
}
变量声明let与var
1. ES5声明变量特点: var
(1)有变量提升 : var声明提升到当前作用域最顶端
(2)没有块级作用域 : 大括号(分支+循环)里面的变量是全局的
2. ES6声明变量特点: let const
(1) 没有变量提升 : 变量必须要先声明,后使用
(2) 有块级作用域 : 大括号(分支+循环)里面的变量是局部的
3. let与const区别 :
let 变量 : 值可以修改的
const 常量 : 值不可以修改, 只能在声明的时候赋值