对象
JS中的一切都可以理解成对象,例如其中的数组、函数、对象等
闭包
1.定义&原理
闭包即一个拥有许多变量和绑定了这些变量的环境的表达式(通常为函数)
闭包利用了变量的作用域链,函数内部可以访问外部的变量和全局变量,而函数外部无法访问函数内部变量
因此,在函数内部定义一个函数,用函数内的函数来访问函数内部的变量,并将该变量存储在内存中
如下的例子中,因为n相对于f2是全局变量,f2依存于f1,因此运行a(实际为f1)之后,n继续保存在内存中不清除
执行nAdd函数后,n变成1000
1 function f1(){ 2 var n = 999; 3 nAdd = function(){ 4 n = n+1; 5 } 6 function f2(){ 7 alert(n); 8 } 9 return f2; 10 } 11 var a = f1(); 12 a();//弹出999 13 nAdd(); 14 a();//弹出1000
2.用途
利用闭包,在函数外读取函数内部的局部变量,并让函数内部的局部变量保存在内存中
3.优缺点
优点:封装性强,可访问局部变量
缺点:局部变量长时间占用内存,容易产生内存泄漏
封装
1.定义&原理
把对象内部数据和操作细节隐藏,只对外提供一个对象的专门访问的接口
JS中,利用闭包来实现封装的效果
用函数内的嵌套函数实现访问函数局部变量的方法,叫做特权方法
1 function f1(){ 2 var n = 1; 3 //此处f2函数可以让用户在函数外访问n,为特权方法 4 this.f2 = function(){ 5 console.log(++n); 6 } 7 //等同于下面的方法 8 function f2(){ 9 console.log(++n); 10 } 11 return f2; 12 } 13 var a = f1(); 14 a();
2.缺点
封装占用了内存,不利于继承
声明对象的方式
1.字面量
直接通过var声明一个对象,并在{}中写出该对象的属性名、属性值、函数(方法)
注意其中属性名需要用引号括起来
1 var myinfo = { 2 'name':'qtfy', 3 'age':24, 4 'hobby':function(){ 5 console.log("I like singing"); 6 } 7 }
2.构造函数
用var声明构造一个Object对象,然后通过对象名.属性名=属性值的方法添加属性和方法
1 var myobj = new Object(); 2 myobj.name = 'qtfy'; 3 myobj.age = 24; 4 myobj.hobby = function(){ 5 console.log("I like singing"); 6 }
3.构造方法
定义一个函数和其形参,在函数内部用this指向当前函数,把传入的参数添加为属性值
定义完成后,构建一个函数的实例
1 function test(name,age,hobby){ 2 this.name = name; 3 this.age = age; 4 this.interest = function(){ 5 console.log('my hobby is '+hobby); 6 } 7 } 8 var person = new test('qtfy',24,'singing');
4.工厂模式
定义一个函数,函数内部var声明构造一个Object对象,并通过对象名.属性名=属性值来给这个对象添加属性和方法,最后返回该对象
可以理解成一个白盒,可以向其中投入参数,返回一系列具有相同属性名、方法的对象,但对象之间彼此独立,没有关联
1 function createObject(name,age,hobby){ 2 var obj = new Object(); 3 obj.name = name; 4 obj.age = age; 5 obj.interest = function(){ 6 console.log('my hobby is '+hobby); 7 } 8 return obj; 9 } 10 var person = createObject('qtfy',24,'singing');
5.原型模式
定义一个空函数(空方法),通过函数的prototype属性来给该空函数添加属性、方法
通过var声明创建一个该函数的实例,以生成一个对象
1 function createObject(){} 2 createObject.prototype.name = 'qtfy'; 3 createObject.prototype.age = 24; 4 createObject.prototype.hobby = function(){ 5 console.log('I like singing'); 6 } 7 var person = new createObject();
此外,对定义的空函数(空方法),可以用prototype属性,以键值对的形式传递一个对象,以作为该空函数的属性名和属性值
该方法叫做json数据(只要是字符串,无论键值都要用引号引起来)
1 function test(){} 2 test.prototype = { 3 'name':'qtfy', 4 'age':'24', 5 'hobby':'singing' 6 }
6.混合模式
用构造方法创建一个函数,在其中用this指向当前函数,把传入的参数赋值为属性值
再用原型模式,给函数添加方法
最后构建一个函数的实例,以创建一个对象
1 function test(name,age){ 2 this.name = name; 3 this.age = age; 4 } 5 test.prototype.hobby = function(){ 6 console.log('my hobby is singing'); 7 } 8 var person = new test('qtfy',24);
对象的遍历和存储
1.遍历对象
通过for i in k语句来遍历对象
其中i为对象中的每一个属性名/方法名,k为对象名
可用k[i]访问每一个属性值/方法的定义代码
2.对象在内存中的存储
内存分为栈内存、堆内存、代码段以及数据段
对象的名称保存在栈内存中,是个指向堆内存中某个对象的地址
堆内存中保存了该对象的属性(名/值)以及方法名,方法名指向代码段
代码段即对象的方法的具体代码