Javascript中的面向对象

1.概述

面向对象:对代码的一种抽象,对外统一提供调用接口的编程思想。

2.名词解释

属性:事物的特性
方法:事物的功能
对象:事物的一个实例
原型:JS函数中有prototype属性引用了一个对象,即原型对象(原型),每个函数都有prototype属性,prototype属性所引用的值也是一个对象(Object),它的作用是定义所有对象实例所共享的属性和方法prototype,对于构造函数来说,它是一个属性;对于对象实例来说,它是一个原型对象。
使用prototype:

function Person(name,height){
this.name=name;
this.height=height;
}
Person.prototype.hobby=function(){
return 'watching movies';
}
var boy=new Person('keith',180);
var girl=new Person('rascal',153);
console.log(boy.name); //'keith'
console.log(girl.name); //'rascal'
console.log(boy.hobby===girl.hobby); //true

此时,若改变prototype上hobby方法的内容,所有Person对象的实例中hobby方法都会跟着改变,除非该对象显式地重新定义了该方法。(优先查找实例方法,若不存在则查找原型对象上的方法。)

不使用prototype:

function Person(name,height){
 this.name=name;
 this.height=height;
 this.hobby=function(){
 return 'watching movies';
}
 }
var boy=new Person('keith',180);
 var girl=new Person('rascal',153);
 console.log(boy.name); //'keith'
 console.log(girl.name); //'rascal'
 console.log(boy.hobby===girl.hobby); //false
闭包:

闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数)。闭包的本质就是在一个函数内部创建另一个函数
全局变量可以在函数内部直接访问,而不需要通过传参访问。但反过来,在外层作用域下无法获取内层作用域下的变量,同样在不同的函数作用域中也是不能相互访问彼此变量的。想在一个函数内部也有限权访问另一个函数内部的变量,就要用到闭包。
闭包的3个特性:
①函数嵌套函数
②函数内部可以引用函数外部的参数和变量
③参数和变量不会被垃圾回收机制回收

函数作为返回值:
例1:

function a(){
	var name = 'zijeak';
	return function(){
		return name;
	};
}
b = a();
b();

打印结果为:zijeak
例2:

function a(){
	var i=0;
	function b(){
		alert(++i);
	}
	return b;
}
var c = a();
c();

打印结果为1
例3:

function fn(){
	var num = 3;
	return function(){
		var n = 0;
		console.log(++n);
		console.log(++num);
	}
}
var fn1 = fn();
fn1();// 1 4
fn1();// 1 5

匿名函数作为返回值,在fn函数调用后返回给fn1,但因为匿名函数内部引用了num,导致其不能随fn调用的结束而销毁,因此num会一直保留在内存中,可以被访问。
闭包的优缺点:
好处
①保护函数内的变量安全 ,实现封装,防止变量流入其他环境发生命名冲突
②在内存中维持一个变量,可以做缓存(但使用多了同时也是一项缺点,消耗内存)
③匿名自执行函数可以减少内存消耗
坏处
①被引用的私有变量不能被销毁,增大了内存消耗,造成内存泄漏,解决方法是可以在使用完变量后手动为它赋值为null;
②其次由于闭包涉及跨域访问,所以会导致性能损失,我们可以通过把跨作用域变量存储在局部变量中,然后直接访问局部变量,来减轻对执行速度的影响

3.声明对象

3.1 JS字面式声明对象

var person = {
	name:'Zhangsan',
	age:26,
	sex:"male",

	eat:function(food){
		alert(this.name+" is eating "+food);
	}
}
person.eat("shit");

3.2 new操作符

person = new Object();
person.name = 'Zhangsan';
person.age = 26;
person.eat = function(food){
	alert(this.name+" is eating "+food);
}

person.eat("apple");

添加构造函数之后:

function Person(name,sex,age){
	this.name = name;
	this.sex = sex;
	this.age = age;
	this.eat = function(food){
		alert(this.name+" is eating "+food);
	}
}
var person = new Person('Zhangsan',26,'male');
person.eat('banana');

3.3 JS中工厂方式声明对象

function createPerson(name,sex,age){
	var person = new Object();
	person.name = name;
	person.sex = sex;
	person.age = age;
	person.eat = function(food){
		alert(this.name+" is eating "+food);
	}
	return person;
}
var person = createPerson('Zhangsan',26,'male');
person.eat('Pear');

3.4 JS中原型模式声明对象

原型模式的根本:函数本身声明为空内容,利用prototype定义一些属性及方法。
好处:让所有实例化的对象都拥有它包含的属性及方法。

定义方式一:

function test(){
}
test.prototype.color = 'red';
test.prototype.height = '1.7';
test.prototype.width = '1.2';
test.prototype.showInfo = function(){
	alert(this.color+"---"+this.height+"---"+this.width);
}
var car = new test();
car.showInfo();

定义方式二:JSON数据定义属性和方法

function test(){
	
}
test.prototype={
	color:'red',
	height:'1.7',
	width:'1.2',
	showInfo:function(){
		alert(this.color+"---"+this.height+"---"+this.width);
	}
}
var car = new test();
car.showInfo();

3.5 JS中混合模式声明对象

function test(color,height,width){
	this.color = color;
	this.height = height;
	this.width = width;
}
test.prototype={
	showInfo:function(){
		alert(this.color+"---"+this.height+"---"+this.width);
	}
}
var car = new test('red','1.7','1.2');
car.showInfo();

4.遍历对象的属性

对象可以当做数组处理,使用for-in循环遍历

//声明
function test(color,height,width){
	this.color = color;
	this.height = height;
	this.width = width;
}
test.prototype={
	showInfo:function(){
		alert(this.color+"---"+this.height+"---"+this.width);
	}
}
var car = new test('red','1.7','1.2');
//遍历
for(var i in car){
	console.log(i);//取属性或方法的名称
	console.log(car[i]);//取属性的值或方法的代码
}

在这里插入图片描述
对象在内存中的分布
索引(地址)存在栈内存
属性和方法名存在堆内存
方法体存在代码段

5.封装

封装(Encapsulation):把对象内部数据和操作细节进行隐藏。Javascript可以通过闭包实现封装。

function demo(){
	var num = 1;
	function get_num(){//特权方法
		return num;
	}
	return get_num;
}
var use_demo = demo();
alert(use_demo());
function demo(){
	function _num(){
		alert("num");
	}
	this.num = function(){
		return _num;
	}
}
var use_demo = new demo();
var a = use_demo.num();
a();
use_demo._num();//错误

6.原型和原型链

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

var person = function(){};
var p = new person();

第一步:var p={} 创建对象
第二步:p.__proto__ = person.prototype
第三步:创建对象(初始化对象)p person.call(p)

例如:

var person = function(){}
person.prototype.say=function(){
	alert("天气挺好");
}
var p = new person();
p.say();

这里的p没有say方法,因此会在p.__proto__中查找,而p.__proto__ = person.prototypeperson.prototype有say方法。
这就说明了,函数对象内有一个隐含属性__proto__,其指向创建该对象的函数对象的原型对象prototype

var person = function(){};
person.prototype.say = function(){
	alert("天气挺好");
}
person.prototype.gongzi = 500;

var programmer = function(){};
programmer.prototype = new person();
programmer.prototype.wcd = function(){
	alert("明天天气也不错");
}
programmer.prototype.gongzi=1000;


var p = new programmer();
//p.say(); //可以调用
//p.wcd();
alert(p.gongzi);
// var p = new programmer();  p.__proto__ = programmer.prototype   = new person();
//var p1 = new person();   programmer.prototype = p1
// p.say(); p.__proto__ --> programmer.prototype ==p1 --->p1.__proto__  ==person.prototype.say();
//原型链实现过程 *** 
继承

JS中的继承实质上是利用原型链,在实例化子类对象时使用父类构造方法进行实例化。

  //父类
   function person(name,age){
    this.name = name;
    this.age  = age;
   }
   person.prototype.sayHello = function(){
    alert("hello");
   }
    //子类
   function student(){};
   student.prototype = new person('zijeak',20);
   student.prototype.grade = 3;
   student.prototype.test = function(){
    alert(this.grade);
   }

   var s = new student();
   s.sayHello();
构造继承

在子类内部构造父类的对象实现继承
在这里插入图片描述

使用call和apply继承

call调动一个对象的一个方法,以另一个对象替换当前对象。
apply应用某一对象的一个方法,用另一个对象替换当前对象。
在这里插入图片描述

7.关键词

instanceof:判断一个变量是否是一个对象的实例

var arr = new Array();
alert(arr instanceof Array);

delete:用于删除对象的属性,不能用于删除方法

delete obj.name;

callapply:用于用来重定义 this 这个对象。
在这里插入图片描述
在这里插入图片描述

callee:返回正在执行的function对象,callee是agruments的一个属性。callee实际上指代函数本身,内容为函数内容。
如果当做属性调用,返回函数内容:arguments.callee
如果当做函数调用,意为在函数内部再次调用本函数,若无退出条件,会发生死循环:arguments.callee()
arguments:js中每个函数都有一个Arguments对象的实例,引用函数的参数(实参),可以用数组下标的方式引用arguments元素,它有length属性,callee属性引用函数自身。

this
this可以在函数内部定义属性/变量(定义出来的是全局变量)
this作为方法调用,构造函数内部this指向当前对象。

function test(){
	this.name="zs";
}

this是call、apply的第一个参数

8.对象冒充

将父类的属性和方法一起传给子类作为特权属性和特权方法
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值