文章目录
1.概念
1.1.对象
对象是属性的集合,一切(引用类型)都是对象,没有方法,方法也是属性。对象都是通过函数创建的。
javascript 中只有2种数据类型:
1.值类型:undefined, number, string, boolean
2.引用类型:除了值类型之外都是引用类型
1.2.函数
函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块。
1.3.原型
每个函数都有一个prototype属性
,每个对象都有一个__proto__属性
,指向的是创建这个对象的函数的prototype 属性。
1.3.1.原型的作用
不使用prototype
属性定义的对象方法,是静态方法
,只能直接用类名进行调用
!另外,此静态方法中无法使用this变量
来调用对象其他的属性
!使用prototype
属性定义的对象方法,是非静态方法
,只有在实例化后才能使用
!其方法内部可以this来引用对象自身中的其他属性
!
原型的灵活性:
在Java和C#
中,你可以简单的理解class是一个模子
,对象就是被这个模子压出来的一批一批月饼
(中秋节刚过完)。压个啥样,就得是个啥样,不能随便动,动一动就坏了
。而在javascript中,就没有模子了,月饼被换成了面团
,你可以捏成自己想要的样子。
1.4.自由变量
在A作用域中使用的变量x
,却没有在A作用域中声明
(即在其他作用域中声明的),对于A作用域来说,X就是一个自由变量
。
1.4.1.自由变量的取值方式
自由变量要到创建这个函数
的那个作用域
中取值——是**创建而不是调用
**,切记切记。
1.5.闭包
Javascript允许使用内部函数,即函数定义和函数表达式位于另一个函数的函数体内
。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时
,就会形成闭包
。
2.对象和函数关系
2.1.对象是通过函数创建的
// Object是通过function定义的
function Object(value) {}
// 对象是通过 new Object()方式创建的
var obj = new Object()
2.2.而函数却又是一种对象
// 函数 Object定义如下
function Object(value) {}
// 实际上它是一种快捷方式,真正的实现方式是下面的方式,所以函数也是一种对象
var Object = new Function()
每个
函数
都有一个默认的prototype
属性值,即原型
,每一个对象
都有一个__proto__
指向创建改对象函数的prototype,
Object的prototype指向的是null。
访问
一个对象的属性
时,先在基本属性中查找
,如果没有,再沿着__proto__
这条链向上找,这就是原型链
。
3.闭包的写法
3.1.给函数添加一些属性
function Circle(r) {
this.r = r;
}
Circle.PI = 3.14159;
Circle.prototype.area = function() {
return Circle.PI * this.r * this.r;
}
var c = new Circle(1.0);
alert(c.area());
3.2.将函数当做值赋给变量
var Circle = function() {
var obj = new Object();
obj.PI = 3.14159;
obj.area = function( r ) {
return this.PI * r * r;
}
return obj;
}
var c = new Circle();
alert( c.area( 1.0 ) );
3.3.new 一个对象,然后给对象添加属性和方法
var Circle = new Object();
Circle.PI = 3.14159;
Circle.Area = function( r ) {
return this.PI * r * r;
}
alert( Circle.Area( 1.0 ) );
3.4.声明一个空的对象
var Circle={
"PI":3.14159,
"area":function(r){
return this.PI * r * r;
}
};
alert( Circle.area(1.0) );
3.5.使用Function方式创建
var Circle = new Function("this.PI = 3.14159;this.area = function( r ) {return r*r*this.PI;}");
alert( (new Circle()).area(1.0) );
总的来说,上面几种方法,第
2中和第4
中较为常见,大家可以根据习惯选择。
3.闭包的用途
3.1.匿名自执行函数
有的函数只需要执行一次,其内部变量无需维护,比如UI的初始化,那么我们可以使用闭包:
var data= {
table : [],
tree : {}
};
(function(dm){
for(var i = 0; i < dm.table.rows; i++){
var row = dm.table.rows[i];
for(var j = 0; j < row.cells; i++){
drawCell(i, j);
}
}
})(data);
3.2.结果缓存
我们开发中会碰到很多情况,设想我们有一个处理过程很耗时的函数对象
,每次调用都会花费很长时间,那么我们就需要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部的引用,从而函数内部的值可以得以保留,这样我们在第二次调用的时候,就会从缓存中读取到该对象。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script src="js/jquery.js"></script>
<div id="id" class="id">缓存测试</div>
<script>
// 生成给定key的value
function getValue(id) {
document.writeln('为:' + id + '创建值');
document.writeln('<br>')
document.writeln('<br>')
return "value is "+ id;
}
var CacheSearchBox = (function () {
var cache = {}, count = [];
return {
// 缓存中搜索方法
search: function (searchId) {
// 如果在缓存中,直接返回缓存中对象
if(searchId in cache) {
document.writeln('从缓存中取数据');
document.writeln('<br>')
return cache[searchId];
}
document.writeln('缓存中无此数据');
document.writeln('<br>')
var value = getValue(searchId);
cache[searchId] = value;
count.push(searchId)
// 保证缓存大小为2
if(count.length > 2) {
document.writeln('缓存量超过最大值,删除最后一个元素');
document.writeln('<br>')
// count.pop() 删除并返回第一个元素
delete cache[count.shift()];
}
document.writeln('当前缓存对象内容:' + JSON.stringify(cache));
document.writeln('<br>')
document.writeln('当前缓存数组内容:' + JSON.stringify(count));
document.writeln('<br>')
},
// 清除缓存方法
clear: function (searchId) {
if(searchId in cache) {
// 删除缓存中的对象
delete cache[searchId];
// 删除缓存数组中的数据
count.splice(count.indexOf(9), 1)
document.writeln('清除缓存对象:' + searchId);
document.writeln('<br>')
document.writeln('当前缓存对象内容:' + JSON.stringify(cache));
document.writeln('<br>')
}
}
};
})();
CacheSearchBox.search('1');
CacheSearchBox.search('1');
CacheSearchBox.search('2');
CacheSearchBox.search('2');
CacheSearchBox.search('3');
CacheSearchBox.clear('3')
</script>
</body>
</html>
3.3.封装
var person = function(){
//变量作用域为函数内部,外部无法访问
var name = "default";
return {
getName : function(){
return name;
},
setName : function(newName){
name = newName;
}
}
}();
print(person.name);//直接访问,结果为undefined
print(person.getName());
person.setName("abruzzi");
print(person.getName());
得到结果如下:
undefined
default
abruzzi
3.4.实现类和继承
function Person(){
var name = "default";
return {
getName : function(){
return name;
},
setName : function(newName){
name = newName;
}
}
};
var p = new Person();
p.setName("Tom");
alert(p.getName());
var Jack = function(){};
//继承自Person
Jack.prototype = new Person();
//添加私有方法
Jack.prototype.Say = function(){
alert("Hello,my name is Jack");
};
var j = new Jack();
j.setName("Jack");
j.Say();
alert(j.getName());