封装
两种封装方式
函数封装
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>函数封装</title>
</head>
<body>
<script type="text/javascript">
(function(){
var a = 3;
var b = 4;
function fn1(){
console.log(a);
};
function fn2(){
console.log(b);
}
/**
* 函数封装的缺点是
* 1.所有函数暴露在全局变量中,容易产生污染问题
* 2.代码冗余,结构不清晰
*
* *** 解决办法
* 对象封装法
*/
})()
</script>
</body>
</html>
对象封装
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>对象封装</title>
</head>
<body>
<script type="text/javascript">
(function(){
var obj = {
// 这里放代码的方法
fn1 : function(){
console.log(1);
},
fn2 : function(){
console.log(2);
}
// 这里放代码的属性
/**
* 对象封装的优点 - 解决了函数封装的问题
* 1.全局只有obj这一个全局变量
* 2.代码结构清晰
*/
}
})()
</script>
</body>
</html>
对象的几种创建方式
1. 对象字面量
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>对象字面量</title>
</head>
<body>
<script type="text/javascript">
(function(){
/**
* 字面量创建对象
* 缺点
* 每次只能创建一个对象,重复性较多,代码冗余
*
*/
var o = {
fn1 : function(){
console.log(1);
}
};
o.fn1(); // 1
})()
</script>
</body>
</html>
2. new内置构造函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>new内置构造函数</title>
</head>
<body>
<script type="text/javascript">
(function(){
/**
* new内置构造函数
* 缺点
* 每次只能创建一个空对象,需要重复性的给对象赋值属性和方法
*/
var o = new Object();
o.name = "jianyan";
o.age = 24;
o.say = function(){
console.log(this.name);
}
console.log(o.name); // jianyan
console.log(o.age); // 24
o.say(); // jianyan
})()
</script>
</body>
</html>
3. 工厂函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>工厂函数</title>
</head>
<body>
<script type="text/javascript">
(function(){
/**
* 工厂函数
*
* 缺点,每次实例化的属性和方法都一样,如何解决?
* 解决,自定义构造函数
*/
function creatObj(){
var obj = new Object();
obj.name = "jianyan";
obj.age = 24;
obj.say = function(){
console.log(this.name);
}
return obj;
}
// 实例化
var o1 = creatObj();
var o2 = creatObj();
o1.say();
// 缺点,每次实例化的属性和方法都一样,如何解决?
// 解决,属性传参和方法分离
function creatObj1(name,age){
var obj = new Object();
obj.name = name;
obj.age = age;
obj.say = say1;
return obj;
}
function say1(){
console.log(this.name);
}
var o3 = creatObj1("jianyan",24);
var o4 = creatObj1("qian",25);
console.log(o3.name); // jianyan
console.log(o4.name); // qian
})()
</script>
</body>
</html>
自定义构造函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自定义构造函数</title>
</head>
<body>
<script type="text/javascript">
(function(){
/**
* 自定义构造函数
* 函数名首字母大写
*
* 问题
* 所有方法都暴露在全局变量
* 代码结构不清晰,代码冗余
* 解决
* 使用原型
*/
function CreateObject(name,age){
// var this = new Object() 浏览器默认创建
this.name = name;
this.age = age;
this.say = say;
/*function(){
console.log(this.name);
}*/
// return this; 浏览器默认创建
}
function say(){
console.log(this.name);
}
// 实例化
var o1 = new CreateObject("jianyan",24);
var o2 = new CreateObject("qian",25);
console.log(o1.name); // jianyan
console.log(o2.name); // qian
})()
</script>
</body>
</html>
原型
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>原型</title>
</head>
<body>
<script type="text/javascript">
(function(){
/**
* 原型
* 什么是原型?
* 在创建构造函数时,此时系统会默认创建并关联一个对象,这个对象就是原型.
* 默认的原型对象中有一个constructor属性执行该构造函数
*
* 原型的作用?
* 原型是一个对象,其属性和方法可以被构造函数创建的实例使用
* *** 实例可以直接访问原型内的属性和方法
*
* 如何给原型对象添加属性和方法?
* 1. prototype
* 构造函数名.prototype.say = function(){} 给原型添加一个say方法
* 2. 直接替换原型对象
* 直接替换原型对象,此时会导致 构造函数,实例,原型对象三者关系改变
* 之前的原型对象也会失效
* *** 小心使用,注意三角关系
*
* 原型是使用注意事项
* 1.使用对象访问属性,先去其构造函数中查找属性,若有,返回属性,没有就会去原型对象查找
* 2.使用对象设置属性,只在对象中查找,若没有,则创建属性,若有,则覆盖属性
* 3.如果在原型对象中有引用类型的属性,那么使用对象进行修改该属性内容
* *** 我们一般讲共享的方法放在原型,属性放在对象中
*
* __proto__ 调试用
* 隐式原型,一个对象的隐式原型指向构造该对象的构造函数的原型,
* 这也保证了实例能够访问在构造函数原型中定义的属性和方法。
*
* 替换原型注意
* 在新替换的原型中,,没有constructor属性,就会影响三角关系
* 所以,新替换原型后,最好手动添加constructor属性,以保证三角关系的稳定
*
* Object.getPrototypeOf()
* 检测某个实例是否是另一个对象的原型对象
*
*
*
*/
var o = new Object();
console.log(o.__proto__ === Object.prototype);
console.log(Object.__proto__ == Function.prototype);
console.log(Function.prototype.__proto__ == Object.prototype);
console.log(Number.__proto__ == Function.prototype);
})()
</script>
</body>
</html>