javascript知识点(五)之 闭包和继承

1,什么是闭包:

        闭包就是能够读取其他函数内部变量的函数。在js中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解为“定义在一个函数内部的函数”。

2,闭包的特点:

        1),可以读取函数内部的变量。

        2),让这些变量的值始终保存在内存中。

3,闭包的原理

        理解闭包,首先必须理解js变量作用域。变量的作用域无非就是两种:全局变量和局部变量。

        js语言的特殊之处,就在于函数内部可以直接读取全局变量。另一方面,函数外部自然无法读取函数内的局部变量。

4:闭包的应用场景

        1:函数作为返回值。

        2:函数作为参数被传递。

扫描二维码关注公众号,回复: 1853938 查看本文章

5:构造函数继承:

        1),第一种继承

//继承的第一种方式
	function Parent(username){
		this.username = username;
		this.hello = function(){
			console.log(this.username)
		}
	}

	function child (username,password){
		//通过一下3行实现继承
		//1,this.method是一个临时属性,并且指向Parent所指向对象,
		//2,执行this.method方法,即执行Parent所指向的对象函数
		//3,删除this.method属性,即此时Child就已经拥有了Parent所有属性和方法
		this.method = Parent;
		this.method(username);//最为关键的一行
		delete this.method;
		
		this.password = password
	}

        2),用call和apply:就是改变函数内部this的指向,二者作用完全一样,知识接受参数的方式不太一样。

                            call是以列表的形式传参 fn.call(obj,arg1,arg2);

                            apply是以数组方式传参 fn.apply(obj,[arg1,arg2])

               call方法是Function类中的方法

                call方法的第一个参数的值赋值给类(即方法)中出现的this

                call方法的第二个参数开始依次赋值给类(即方法)所接受的参数

                 apply方法接受2个参数,

                 A、第一个参数与call方法的第一个参数一样,即赋值给类(即方法)中出现的this

                 B、第二个参数为数组类型,这个数组中的每个元素依次赋值给类(即方法)所接受的参数

	function Parent(username){
		this.username = username;
		this.hello = function(){
			console.log(this.username)
		}
	}

	function child (username,password){
		Parent.call(this,username)

		
		this.password = password;
		this.word = function(){
			alert(this.password);
		}
	}

	function child1 (username,passworf){
		parent.apply(this,new Array(username));
		
		this.password = password;
		this.word = function(){
			alert(this.password);
		}
		
	}

        3),原型

         构造函数的缺点:JavaScript 通过构造函数生成新对象,因此构造函数可以视为对象的模板。实例对象的属性和方法,可以定义在构造函数内部。同一个构造函数的多个实例之间,无法共享属性,从而造成对系统资源的浪费。

        prototype概念:每一个构造函数都有一个prototype属性,这个属性会在生成实例的时候,成为实例对象的原型。

        JavaScript 的每个对象都继承另一个对象,后者称为“原型”(prototype)对象。一方面,任何一个对象,都可以充当其他对象的原型;另一方面,由于原型对象也是对象,所以它也有自己的原型。null也可以充当原型,区别在于它没有自己的原型对象。

        JavaScript 继承机制的设计就是,原型的所有属性和方法,都能被子对象共享。

function Animal(name) {
  this.name = name;
}
Animal.prototype.color = 'white';
var cat1 = new Animal('大毛');
var cat2 = new Animal('二毛');
cat1.color // 'white'
cat2.color // 'white'
         上面代码中,构造函数Animal的prototype对象,就是实例对象cat1cat2的原型对象。原型对象上添加一个color属性,结果,实例对象都继承了该属性。

        

    4)原型链

    对象的属性和方法,有可能定义在自身,也有可能定义在它的原型对象。由于原型本身也是对象,又有自己的原型,所以形成了一条原型链(prototype chain)。比如,a对象是b对象的原型,b对象是c对象的原型,以此类推。

如果一层层地上溯,所有对象的原型最终都可以上溯到Object.prototype,即Object构造函数的prototype属性。那么,Object.prototype对象有没有它的原型呢?回答是有的,就是没有任何属性和方法的null对象,而null对象没有自己的原型。

         “原型链”的作用是,读取对象的某个属性时,JavaScript 引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如果还是找不到,就到原型的原型去找。如果直到最顶层的Object.prototype还是找不到,则返回undefined

如果对象自身和它的原型,都定义了一个同名属性,那么优先读取对象自身的属性,这叫做“覆盖”(overriding)。

需要注意的是,一级级向上,在原型链寻找某个属性,对性能是有影响的。所寻找的属性在越上层的原型对象,对性能的影响越大。如果寻找某个不存在的属性,将会遍历整个原型链。

        5):原型链的继承

        将一个构造函数的原型指向另一个构造函数的实例对象来实现继承。

function Box() {							//Box构造
	this.name = 'Lee';
}
function Desk() {							//Desk构造
	this.age = 100;
}
Desk.prototype = new Box();					//Desc继承了Box,通过原型,形成链条
var desk = new Desk();
alert(desk.age);
alert(desk.name);							//得到被继承的属性

function Table() {							//Table构造
this.level = 'AAAAA';
}							

Table.prototype = new Desk();				//继续原型链继承

var table = new Table();
alert(table.name);							//继承了Box和Desk

        6),混合继承

         组合继承就是结合使用原型链与构造函数的优点,组合而成的一个模式。实现也很简单,既然是结合,那当然结合了两方的优点

         即原型链继承方法,而在构造函数继承属性

function Box(age) {
	this.name = ['Lee', 'Jack', 'Hello']
	this.age = age;

}

Box.prototype.run = function () {				
		return this.name + this.age;
};

function Desk(age) {
	Box.call(this, age);						//对象冒充   继承了 name 和age 属性

}

Desk.prototype = new Box();					//原型链继承  run方法

var desk = new Desk(100);
alert(desk.run());


 

猜你喜欢

转载自blog.csdn.net/hlyphard/article/details/79739392
今日推荐