面向对象、过程编程
面向过程编程:按照步骤一步一步执行,性能比面向对象高
面向对象编程:把事务分解成一个一个对象,发现对象有哪些功能,然后由对象分工合作完成。代码灵活,可复用性。
面向对象特征:封装性、继承性、多态性
ES6中类和对象
1)类:抽象对象的公共部分,泛指某一大类
抽取(抽象)对象共用的属性和行为封装成一个类(模板)
2)对象:
对象是一个具体的事物,在javascript中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象。
对象由属性和方法组成。
对类进行实例化,获取类的对象
es6创建类
语法:
class name{}
//创建实例:
var xx=new name();
注意:类必须用new实例化对象
// 创建明星类
class star{
constructor(uname){
this.uname=uname
}
}
//实例
var ldh=new star('刘德华')
console.log(ldh.uname)
//类constructor构造函数
constructor方法是类的构造方法,用于传递参数返回实例对象,
通过new命令生成对象实例时,自动调用该方法。
如果没有显式定义会自动给我们创建一个constructor()
es6类中添加方法
直接在类中添加即可
// An highlighted block
class star{
constructor(uname){
this.uname=uname
}
sing(){
console.log("我唱歌")
}
}
es6类的继承
子类继承父类的一些属性和方法 extends
class Father{
constructor(){}
money(){
console.log(" 爸爸的钱")
}
}
class Son extends Father{
}
var son=new Son()
son.money()
super关键字
super关键字用于访问和调用对象父类上的函数,可以调用父类的构造函数也可以调用父类的普通函数。
class Father{
constructor(x,y){
this.x=x;
this.y=y;
}
sum(){
console.log(this.x+this.y)
}
}
class Son extends Father{
constructor(x,y){
super(x,y) //调用父类中的构造函数
}
}
var son=new Son(1,2)
son.sum()
继承中如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的,如果子类里面没有就去查找父类有没有这个方法,如果有就执行父类的这个方法(就近原则)
// An highlighted block
class Father{
say(){
console.log("爸爸说")
}
}
class Son extends Father{
say(){
console.log("儿子说")
console.log(super.say())
}
}
var son=new Son()
son.say()
es6子类继承父类方法
子类继承父类加法,扩展减法
// An highlighted block
class Father{
constructor(x,y){
this.x=x;
this.y=y;
}
sum(){
console.log(this.x+this.y)
}
}
class Son extends Father{
constructor(x,y){
super(x,y)
this.x=x;
this.y=y;
}
substrct(){
console.log(this.x-this.y)
}
}
var son=new son(1,2)
son.sum()
son.substrct()
es6中类和对象注意点
1) es6中没有变量提升,所以必须先定义类,才能通过类实例化对象
2)类里边共有的属性和方法一定要加this使用
3)类中this指向
<script>
var that;
class Star{
constructor(uname,age){
this.uname=name;
this.age=age
this.btn=document.querySelector('button');
this.btn.onclick=this.sing
}
sing(){
//this中指向的是btn这个按钮,因为这个按钮调用了这个函数
console.log(this)
console.log(that.uname)
}
}
var ldn=new Star("刘德华",12)
</script>
构造函数和原型
1)构造函数创建对象
2)原型作用
3)访问对象成员规则
构造函数
es6之前,对象基于构造函数创建
创建对象通过以下三种方式:
1)对象字面量
2)new Object()
3)自定义构造函数
<script>
//1.new Object()创建对象
var obj1=new Object()
//2. 利用对象字面量创建对象
var obj2={};
//3.利用构造函数创建对象
function Star(uname,age){
this.uname=uname
this.age=age
this.sing=function(){
console.log("唱歌")
}
}
var ldh=new Star("ldh",18)
ldh.sing()
</script>
构造函数是一种特殊的函数,主要用来初始化对象,它与new一起使用。
new在执行过程中会做四件事:
1)内存中创建一个空对象
2)让this指向这个空对象
3)执行构造函数里边的代码,给这个新对象添加属性和方法
4) 返回这个对象
// 构造函数中的属性和方法我们称为成员,成员可以添加
function Star(uname,age){
this.uname=uname
this.age=age
this.sing=function(){
console.log("唱歌")
}
}
var ldh=new Star('刘德华',18);
//实例成员就是构造函数内部通过this添加的成员,uname,age,sing就是实例成员
//实例成员只能通过实例化的对象来访问
//2.静态成员 在构造函数本身删添加的成员
例如:Star.sex='男'
原型
构造函数存在浪费空间的情况
function Star(uname,age){
this.uname=uname
this.age=age
this.sing=function(){
console.log("唱歌")
}
}
Star.prototype.sing=funciton(){console.log("唱歌")}
var ldh=new Star('刘德华',18)
var zxy=new Star('zhangxuyo',19)
ldh.sing!==zxy.sing
构造函数原型prototype(原型对象)
构造函数通过原型分配的函数是所有对象所共享的
javascript规定每一个构造函数都有一个prototype属性,指向另一个对象,这个prototype就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。
问答:
1.原型是什么?
原型是一个对象,我们称prototype为原型对象
2.原型的主要作用?
共享方法
构造函数是一种特殊的方法,主要用来创建对象时初始化对象。每个构造函数都有prototype(原型)属性,每个函数都有prototype(原型)属性,这个属性是一个指针,指向一个对象,这个对象的用途是包含特定类型的所有实例共享的属性和方法,即这个原型对象是用来实例共享属性和方法的。而每个实例内部都一个指向原型对象的指针。
对象原型 proto
对象都会有一个__proto__指向构造函数的prototype原型对象,之所以我们对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象有__proto__原型的存在。
__proto__对象原型和原型对象prototype是等价的
constructor构造函数
对象原型(proto)和构造函数(prototy)原型对象 里边都有一个属性constructor属性,constructor我们称为构造函数,因为他指回构造函数本身。
function Star(uname,age){
this.uname=uname;
this.age=age
}
Star.prototype.sing=function(){
console.log('我会唱歌')
}
Star.prototype.movie=function(){
console.log('我会电影')
}
var ldh=new Star('刘德华',18)
var zxy=new Star('张学友',19)
console.log(Star.prototype.constructor);
console.log(ldh.__proto__.constructor)
//指回原来的构造函数
Star.prototype={
//如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用
//constructor指回原来的构造函数
constructor:Star,
sing:function(){}
movie:function(){}
}
构造函数、实例、原型对象之间的关系
原型链
创建一个Array对象var arr=[1,2,3],其原型链是:
arr----->Array.prototype---->Object.prototype------>null
Array.prototype定义了indexOf()、shift()等方法,因此你可以在鄋Array对象上直接调用这些方法。
创建一个函数时:
function foo(){ return 0;}
函数也是一个对象:原型链是:
foo---->Function.prototype---------->Object.prototype------->null
js的成员查找机制
1)当访问一个对象的属性(包括方法)时,首先查找这个对象有没有该属性
2)如果没有就查找它的原型(也就是__proto__指向的prototype原型对象)
3)如果还没有就查找原型对象的原型(Object的原型对象)
4)依次类推一直找到Object位置(null)
继承 终于搞明白了哈哈哈哈
es6之前并没有提供extends继承,我们可以通过构造函数+原型对象模拟实现继承,被称为组合继承。
1)call 调用这个函数,修改函数运行时的this指向
fun.call(thisArg,arg1,arg2)
借用构造函数继承父类型属性
核心原理:通过call()把父类型的this指向子类型的this,这样就可以实现子类型继承父类型的属性。
//借用父构造函数继承属性
//1.父构造函数
function Father(uname,age){
//this指向父构造函数的对象实例
this.uname=uname;
this.age=age;
}
//2.子构造函数
function Son(uname,age){
//this指向子构造函数的对象实例
//调用父构造函数,将父构造函数的this改为子构造函数的this
Father.call(this,uname,age)
}
var son=new Son('ldh',18)
console.log(son)
相当于给子构造函数的this对象添加了uname和age属性。
借用原型对象继承父类型方法
function Father(uname,age){
this.uname=uname;
this.age=age
}
Father.prototype.money=function(){
console.log(100000000)
}
function Son(uname,age){
Father.call(this,uname,age)
}
//Son.prototype=Father.prototype //图一 这样赋值会有问题,如果直接修改了子原型对象,父原型对象也会一起变化
Son.prototype=new Father(); //实例化父构造函数 图二:
//如果利用对象的形式修改了原型对象,别忘了利用constructor指向原来的构造函数
Son.prototype.constructor=Son;
//这个是子构造函数专门的方法
Son.prototype.exam=function(){
console.log('孩子要考试')
}
var son=new Son('刘德华',18);
console.log(son);
console.log(Father.prototype);
console.log(Son.prototype.constructor)
图一:
图二:
共有的方法,写到原型对象上
原型对象this指向
<script>
function Star(uname,age){
this.uname=uname;
this.age=age;
}
Star.prototype.sing=function(){
console.log('我会唱歌')
}
var ldh=new Star('刘德华',18)
//在构造函数中,里面this指向的是对象ldh
</script>
es5中的新增方法
数组方法
迭代遍历方法:forEach()、map()、filter()、some()、every()
array.forEach(function(currentValue,index,arr))
currentValue:数组当前项的值
index:数组当前项的索引
arr:数组对象本身