JS对象的概念、声明方式等及js中的继承与封装

对象的遍历

对象可以当做数组处理,使用for in

var person={};
person.name="cyy";
person.age=25;
person.infos=function(){
    alert(this.name+" "+this.age);
}

for(var i in person){
    console.log(i);//属性名或方法名
    console.log(person[i]);属性值或方法值
}

 

 使用构造函数声明的对象,需要实例化之后再进行遍历

 Person(){
    this.name="cyy";
    this.age=25;
}
var p=new Person();
 p){
    console.log(i+":"+p[i]);
}

对象在内存中的分布

参考以下神图

 

 

 封装:把对象的内部数据和操作细节进行隐藏

提供private关键词隐藏某些属性和方法,限制被封装的数据或者内容的访问,只对外提供一个对象的专门访问的接口

接口一般为调用方法

不过js没有提供这样的关键词,但可以通过闭包来实现

函数内部声明的变量,外部是访问不到的

 fn(){
    var n=1 fn2(){//特权方法
        alert(++n);
    }
    return fn2;
}
fn()();2
封装
var name="cyy" _name(){
        alert(name);
    }
    this.name=function(){这是给外部的接口
         _name;
    }
}
var fn=p.name();
fn();cyy

封装的缺点:1、占用内存   2、不利于继承

 

利用闭包特性来封装一个对象student,运用对象student存储一个学生的信息,信息包括姓名,性别和年龄,这些信息不可被外部直接访问,只能通过对象的方法获取 

student的数据结构如下:

 

 

 Student(){
    var obj={};
     _set(name,sex,age){
        obj.name=name;
        obj.sex=sex;
        obj.age=age;
    }
     _get(){
        return obj.name+" "+obj.sex+" "+obj.age;
    }
    obj.get=对外接口
         _get;
    }
    obj.set= _set;
    }
     obj;
}
var stu= Student;
stu.set()("小明","男",23);
console.log(stu.get()());小明 男 23

原型和原型链

原型:利用 prototype 添加属性和方法,prototype对象

原型链:JS在创建对象时,有一个 __proto__ 的内置属性,指向它的原型对象 prototype

var Person=(){}
 Person();
Person.prototype.say=(){
    alert("老娘超美");
}
p.say();
/*
p没有say方法,所以会去p.__proto__里找
p.__proto__是一个对象,指向Person.prototype
Person.prototype中有say方法
 */



创建对象的过程
1、创建对象 var p={}
2、将Person的原型对象赋值给p  p.__proto__=Person.prototype
3、初始化对象p  Person.call(p)
 */
alert(p.__proto__==Person.prototype);true

原型和原型链,实现原型继承

function(){}Person是一个对象
Person.prototype.say=(){
    alert("陈莺莺超美");
}
var Cyy=function(){};Cyy也是一个对象
Cyy.prototype=new Person();将Cyy的原型指向Person,实现Cyy继承自Person
Cyy.prototype.sing=(){
    alert("陈莺莺会唱歌");
}

var me= Cyy();
me.say();陈莺莺超美
me.sing(); 陈莺莺会唱歌


分析:me.__proto__  ->  Cyy.ptototype  -> Person.prototype
Person是父  Cyy是子
继承:如果子类中没有的,会继承自父类;如果子类和父类中都有,那么子类的会覆盖掉父类的
 */

__proto__ 实现原型继承

 Person(name,age){
    name;
    this.age=age;
}
Person.prototype.say= Student(){};
Student.prototype=new Person("cyy",25);
Person是Student的父类
//子类必须继承自父类的实例
Student.prototype.grade=3;
Student.prototype.test=.grade);
}

var s= Student();
s.say();cyy 25
s.test();3s.__proto__ -> Student.prototype -> Person.prototype

原型的值可以是一个对象,也可以是null

原型链的最终指向null

alert(Object.prototype.__proto__);null
 情况一
 Parent(){
    this.name="parent"this.age=45 Child(){
    ;
}
Child.prototype.name="child";
Child.prototype= Parent();
var c= Child();
console.log(c.name);parent

 情况二
;
}
Child.prototype= Parent();
Child.prototype.name="child";
child

情况一中,Child.prototype=new Parent(); 这一句覆盖掉了前面的 Child.prototype.name="child";

属性的值与代码执行顺序有关,后继承的父级的,会覆盖住先定义的自己的

 

创建一个动物类的对象,对象中有动物名称和数量的属性 。创建一个猫的对象并继承动物类对象 ,并为猫对象定义一个方法 。实例化一个猫对象 ,调用其方法 ,弹出动物名称和数量

 Animal(name,number){
    this.number=number;
}
 Cat(){};
Cat.prototype=new Animal("cat",30);
Cat.prototype.info=.number);
}
 Cat();
c.info();cat 30

构造函数的继承

在子类内部构造父类的对象来实现继承

父对象被子对象继承后,所有的属性和方法,都会传递到子对象中

 Parent(name){
    this.pSay=(){
        alert(.name);
    }
}
 Child(name,1)">this.obj=Parent;
    this.obj(name);继承了父元素中的两句代码
    age;
    this.cSay=.age);
    }
}
new Parent("爸爸");
p.pSay();爸爸
new Child("女儿",1)">);
c.cSay();女儿 25
c.pSay();女儿

对象内置方法中的apply和call都可用于继承,两者的区别在于传参方式不同

obj.call( 方法,var1,var2...)

obj.apply( 方法,[var1,var2...])

 Parent(name,age,sex){
    this.sex=sex;
    this.say=this.age+" "+.sex);
    }
}
实现继承
    Parent.call(this,name,age);this是指Child
}
 Child2(name,1)">实现继承
    Parent.apply(}

new Child("cyy",1)">);
c.say();
cyy 25 undefinedChild也拥有了Parent的属性和方法
var c2=new Child2("cyy2",1)">);
c2.say();cyy2 25 undefined

使用构造方法创建一个动物类对象Animal, 对象中定义属性有动物名称和数量,并且定义一个方法。再创建两个动物的对象(如猫和狗),一个动物使用call方法实现继承Animal, 一个动物使用apply方法实现继承Animal。分别实例化两个动物并弹出动物的名称和数量

this.num=num;
    this.getInfo=.num);
    }
}
 Cat(name,num){
    Animal.call(,num);
}
 Dog(name,num){
    Animal.apply(new Cat("cat",20);
c.getInfo();cat 20
var d=new Dog("dog",1)">);
d.getInfo();dog 30

JS面向对象的关键词

instanceof  变量是否是对象的实例

var arr= Array();
console.log(arr instanceof Array);true
console.log(arr instanceof Object);true

 Person(){};
 Person();
console.log(p instanceof Person);true
console.log(p true

 

delete 删除对象属性(不能删除原型链中的属性和方法

this.eat=(){
        alert("吃饭");
    }
}
 Person();
console.log(p.name);cyy
delete p.name;删除对象的属性
console.log(p.name);undefined

p.eat();吃饭
delete p.eat();吃饭  删除对象的方法,失败
p.eat();吃饭

;
console.log(name);delete name;
console.log(name);name is not defined

 

call 参数逐个实现继承

apply 参数以数组方式实现继承

 add(a,b){
    alert(a+b);
}
 sub(a,b){
    alert(a-b);
}
add.call(sub,4,812 调用的是add这个方法
add.call(sub2,4,1)">sub2 is not defined 只能引用一个已经存在的对象

add.apply(sub,[3,2]);
 Animal(){
    this.name="animal"this.show= Cat(){
    this.name="cat"var a= Animal();
 Cat();
a.show.call(c);cat c拥有了a所拥有的show方法
a.show.apply(c,[]);cat c拥有了a所拥有的show方法

创建两个数组 ,并运用apply实现两个数组的拼接

var arr1=[2,3];
var arr2=[4,5];
arr1.push.apply(arr1,arr2);
调用的是apply前面的方法:arr1.push
console.log(arr1);

 

arguments 实参的类数组对象

callee  返回正在执行的function对象,返回的是function的内容

arguments.callee

 fn(){
    console.log(arguments.callee);
    ƒ fn(){
        console.log(arguments.callee);
        }
    */
    console.log(arguments.callee());不停调用自身,陷入死循环
}
fn();

 

常用于递归函数调用函数自身

var sum=(n){
    if(n<=1) return 1return n+sum(n-1);
}
console.log(sum(4));10
return n+arguments.callee(n-110

 

this 指向当前对象

1、this函数调用

var x=1this.x=2;this改变的是全局变量的x的值
}
fn();
console.log(x);2

2、this作为方法调用

构造函数内指代当前对象

 Person();
p.show();cyy

3、在call和apply中,this作为第一个参数

 show(){
    alert(.name);
}
{};
obj.name="cyy2";
obj.showName=show;
obj.showName.apply();调用show(),this指向全局
obj.showName.apply(window);同上
obj.showName.apply(obj);调用show(),this指向obj

用arguments计算参数总和

 sum(){
    var sum=0var i=0;i<arguments.length;i++){
        sum+=arguments[i];
    }
     sum;
}
console.log(sum(2,5,7));14

对象冒充:将父类的属性和方法传给子类,作为特权属性和特权方法

this.name=name;特权属性
    特权方法
        alert(.age);
    }
}
Parent.prototype.walk=非特权方法
    alert("walking..."this.obj=Parent;对象冒充,可以使用父类的特权属性和特权方法
    .obj(name,age);
    sex;
}
);
c.show();cyy 25
c.walk(); c.walk is not a function

 

相关文章

kindeditor4.x代码高亮功能默认使用的是prettify插件,prett...
这一篇我将介绍如何让kindeditor4.x整合SyntaxHighlighter代...
js如何实现弹出form提交表单?(图文+视频)
js怎么获取复选框选中的值
js如何实现倒计时跳转页面
如何用js控制图片放大缩小