04、JS面向对象

js面向对象的名词解析

属性:事物的特征

方法:事物的功能

对象:事物的实例

原型:js函数中由prototype属性引用了一个对象,即原型对象

 

js闭包

闭包:闭包是一个拥有许多变量和绑定这些变量的环境的表达式(通常是一个函数)。

闭包的优点:有利于封装,可以访问局部变量。

闭包的缺点:内存占用严重,容易产生内存泄漏。

 

声明对象的方法

字面式:

var person = {
name : "ming",
sex : "male",
age : 18
};
console.log(person.name); //对象名.属性名 调用

 

Object方式:

//Object是所有对象的基类、根,所有的JavaScript对象都是由Object延伸的。

var person = new Object();
person.name = "ming";
person.sex = "male";
person.age = 18;
console.log(person.name); //对象名.属性名 调用

 

构造方式:

function Person(name,sex,age){
this.name = name; //this.name指的是name属性。后面的name指的是参数。
this.sex = sex;
this.age = age;
}
var per = new Person("ming","male",18); //使用前要先实例化对象
console.log(per.name); //实例化的名.属性名 调用

 

工厂方式:

function person (name,sex,age){
var ren = new Object();
ren.name = name; //ren.name指的是name属性。后面的name指的是参数。
ren.sex = sex;
ren.age = age;
return ren; //工厂方式必须返回对象
}
var xx = person("ming","male",18); //使用前要先实例化对象
console.log(xx.name); //实例化的名.属性名 调用

 

构造方式和工厂方式的区别:

构造方式:不会显示创建对象,将属性赋值给this,不需要return对象。

工厂方式:在方法内部创建Object对象,返回Object对象,属性和方法都是赋给Object对象。

 

原型模式:

//任何js方法或函数,都自带一个prototype属性,且它以对象方式存在。

//原型模式根本:函数本身声明为空内容,利用prototype定义一些属性及方法。

function person(){ }
person.prototype.name = "ming";
person.prototype.sex = "male";
person.prototype.age = 18;
var ren = new person();
console.log(ren.name);

或 json数据定义属性和方法

function person(){ }
person.prototype ={
name : "ming",
sex : "male",
age : 18
}
var ren = new person();
console.log(ren.age);

 

混合模式:

//构造方式  +  原型模式

function person(name,sex,age){
this.name = name;
this.sex = sex;
this.age = age;
}
person.prototype = {
address : "beijing",
add : function(a,b){
return a+b;
}
}
var ren = new person("ming","male",18);
console.log(ren.name);
console.log(ren.add(1,1));

 

 

对象的遍历

for in 方法(用什么方式声明的对象都可以遍历,有些需要先实例化)

如:

function person(){ }
person.prototype.name = "ming";
person.prototype.sex = "male";
person.prototype.age = 18;
var ren = new person();
// console.log(ren.name);

for(var i in ren){
console.log(i); //i为属性名
console.log(ren[i]); //ren[i]为属性值
}

 

 

对象的存储

存储分为:栈内存(基本类型)、堆内存(引用类型)、代码段(应用类型里面的方法)、数据段

 

封装

封装:把对象内部数据和操作细节进行隐藏。(大多面向对象的语言都支持封装的特性,提供了private关键字来隐藏某些属性或方法,用来限制被封装的数据或者内容的访问,只对外提供一个对象的专门访问的接口。接口一般为调用方法)

注:JavaScript不支持封装的关键词,但是可以通过闭包实现封装。

 

原型链继承

原型:是利用prototype添加属性和方法

原型链:JS在创建对象(不论普通对象还是函数对象)的时候,都有一个叫做__proto__的内置属性,用于指向创建它的函数对象的原型对象prototype

function person(){
this.name = "小明";
}
person.prototype.age = function(){
alert(18);
};
var stu = new person;
//1、var stu={} –>
//2、stu.__proto__ = person.prototype –>
//3、对象初始化
stu.age();//stu为变量,没有age方法,
//会从stu.__proto__里面找,stu.__proto__等于person.prototype,
//在person.prototype里面恰好找到了age方法

 

原型继承方法
1、定义父类型构造函数
2、给父类型的原型添加方法
3、定义子类型的构造函数
4、创建父类型的对象赋值给子类型的原型
5、将子类型原型的构造属性设置为子类型
6、给子类型原型添加方法
7、创建子类型的对象:可以调用父类型的方法
重点:子类型的原型为父类型的一个实例对象

// 1、定义父类型构造函数
function fulei(){
this.name = "小明";
}
// 2、给父类型的原型添加方法
fulei.prototype.say = function(){
alert("父类");
}
// 3、定义子类型的构造函数
function zilei(){
this.name ="小东";
}
// 4、创建父类型的对象赋值给子类型的原型
zilei.prototype = new fulei();
// 5、将子类型原型的构造属性设置为子类型
zilei.prototype.constructor = zilei;
// 6、给子类型原型添加方法
zilei.prototype.talk = function(){
alert("子类");
}
// 7、创建子类型的对象:可以调用父类型的方法
var ssr = new zilei();
ssr.say(); //父类
// ssr.talk(); //子类
// alert(ssr.name); //小东

 

优点:

  • 父类新增原型方法/原型属性,子类都能访问到
  • 简单,易于实现

缺点:

  • 要想为子类新增属性和方法,必须要在zilei.prototype = new fulei();这样的语句之后执行,不能放到构造器中
  • 无法实现多继承
  • 来自原型对象的所有属性被所有实例共享
  • 创建子类实例时,无法向父类构造函数传参

 

构造函数继承

构造函数继承:在子类内部构造父类的对象实现继承。

构造函数继承方法
1、定义父类型构造函数
2、给父类型添加方法或属性
3、定义子类型构造函数
4、创建子类型属性为父类型本身
5、执行该子类型
6、给子类型添加其他方法或属性
7、实例化子类型:可以调用父类型的方法

function parents(){// 1、定义父类型构造函数
this.name = "zhangsan";// 2、给父类型添加方法或属性
this.age = 18;
}
function child(){// 3、定义子类型构造函数
this.ch = parents;// 4、创建子类型属性为父类型本身
this.ch();// 5、执行该子类型
this.abc = 134343;// 6、给子类型添加其他方法或属性
}
var a = new child();// 7、实例化子类型:可以调用父类型的方法
alert(a.name);
alert(a.abc);

 

 

call/apply继承方法(属于构造函数继承)
1、定义父类型构造函数
2、给父类型添加方法或属性
3、定义子类型构造函数
4、用call/apply方法,把当前对象的值传给父类型
5、定义子类型方法或属性
6、实例化子类型:可以调用父类型的方法

function parents(name,age){// 1、定义父类型构造函数
this.say = function(){// 2、给父类型添加方法或属性
alert("我是父亲"+name+"我今年"+age+"岁");
}
}
function child(name,age){// 3、定义子类型构造函数
// parents.call(this,name,age); // 4、用call/apply方法,把当前对象的值传给父类型
parents.apply(this,[name,age]);
this.abc = 234343243;// 5、定义子类型方法或属性
}
var b = new child("张三",35);// 6、实例化子类型:可以调用父类型的方法
b.say();
alert(b.abc);

 

 

面向对象关键词

 instanceof:判断变量是否是对象的实例(a instanceof Object)

        delete:删除对象属性,删除不了原型链的属性,删除不了变量(delete  a.name)

call、apply:两个方法的作用一样,改变this的指向。call可以有多个参数;apply只能有两个参数,第二个参数必须是数组。(可以只带一个参数,一个参数表示this的指向)

        callee:返回正在执行的function对象(function的内容)。(arguments.callee)。(callee是auguments的一个属性。arguments.callee表示function内容,auguments.callee()表示在函数内容里调用本函数。)

arguments:类数组(所有函数都有)。arguments.length表示参数的个数,还可以用数组下标表示参数内容arguments[i]

this:

1、可以在函数内部定义属性(function (){ this.x=123;alert(this.x); }()  //里面的x是全局变量)

2、作为方法调用,构造函数内this指向当前对象(function person(){ this.name="zhang";this.age=18; })

3、call、apply的第一个参数,改变this的指向。

 

对象冒充

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

function person(name,age){
this.name = name;
this.age = age;
this.sayHi = function(){
alert("hi");
}
}
person.prototype.walk = function(){
alert("walk");
}

//混合的方式声明对象,上面构造是特权属性和方法,下面原型是共有属性和方法。

function student (name,age,grade){
this.newMethod = person;
this.newMethod(name,age);
this.grade = grade;
}
var s1 = new student("zhangsan",15,9);
//s1继承了person的特权属性和方法,没有继承共有属性和方法。

// alert(s1.name); //继承了person的name
// alert(s1.grade);//student自带的grade
// s1.walk();//报错。共有属性和方法无法继承

 

posted @ 2020-03-14 11:50  JaydenQiu  阅读(125)  评论(0)    收藏  举报