版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34664239/article/details/88287872
一、面向对象和基于对象
- 面向对象有三大特性:封装、继承、多态
- 基于对象:有封装的概念,但是实现不了真正的继承。通常是使用对象,但是无法利用现有的对象模板产生新的对象类型,继而产生新的对象,也就是说“基于对象”没有继承的特点。
- JavaScript是基于对象的语言,有三大特点:基于对象、多范式(多样化,没有统一的标准,比如创建对象和数组的方式)、动态性
面向对象:是先有一个抽象的对象描述(类),然后根据这个描述去构建新的对象(实例化对象),就好像盖房子,这个是根据图纸盖
基于对象:是先有一个具体的对象,然后根据这个具体的对象,再去创建新的对象(实例化对象),就好像盖房子,这个是根据盖好的房子的样子盖
原型链
- 原型:把所有可以共享的数据放在同一个对象中,再创建对象的时候,不会出现代码冗余,节省内存。(作用:实现同类对象之间的数据共享)
- 只要是函数,都会有原型。由此函数创建出来的对象,都能访问原型上的成员
- 获取原型:
- 通过函数:fnName.prototype
- 通过对象:obj.proto
- //获取对象的原型兼容处理
function getPrototype(obj){
return obj.__proto__ ? obj.__proto__ : obj.constructor.prototype;
}
原型特点:动态性、唯一性、不可变性、共享性
- 动态性:在已有的原型上添加成员,会反应到创建出来的对象上
如果置换了已有的原型,那么会反映到后来创建的对象上,对已经创建出来的对象没有影响 - 唯一性:由同一个构造函数创建出来的所有对象,都共享一个原型
- 不可变性:通过对象不能修改原型上的值(只能通过修改原型,来改变原型的属性值)
- 共享性:所有对象都可以直接访问原型上的成员
注意:在函数创建的对象上,给原型加方法,仍然可以共享
二、原型链
只有函数有原型prototype!
所有对象都有__proto__属性!
对象的 proto 属性指向创建该对象的函数的 prototype!
函数的 proto 属性指向 Function.prototype!
函数的原型的构造函数指向该函数!
函数的原型的__proto__属性指向Object.prototype!
Object.prototype的__proto__属性指向null!
//对象是由函数生成的,对象的__proto__属性是从生成它的函数的prototype那里得来的
var obj = {};//var o = Object();//Object函数
console.log(obj.__proto__ === Object.prototype )
//普通函数创建对象
var f = function(){};
var a = new f;
console.log(a.__proto__ === f.prototype )
//函数对象都是由Function函数生成的:
function fn(){}
console.log(fn.__proto__ === Function.prototype)
//Function函数本身作为对象时,生成它的函数是他自身!
console.log(Function.__proto__ === Function.prototype)
//Object函数既然是函数,那生成它的函数自然是Function函数
console.log(Object.__proto__ === Function.prototype)
//一般函数默认的prototype是一个类型为"object"的对象,
//它有两个属性:constructor和 __proto__。
//其中constructor属性指向这个函数自身,__proto__属性指向Object.prototype,这说明一般函数的prototype属性是由Object函数生成的。
function ff(){}
console.log(ff.prototype.constructor === ff)
console.log(Function.prototype.constructor === Function)
console.log(ff.prototype.__proto__ === Object.prototype)
//特殊情况:JavaScript原型链的终点
console.log(Object.prototype.__proto__ === null)
console.log(Function.prototype.__proto__ === Object.prototype)
/*
用instanceof,来判断__proto__走向
instanceof
的作用:用于判断实例属于哪个构造函数。
instanceof
的原理:判断实例对象的__proto__
属性,和构造函数的prototype
属性,是否为同一个引用(是否指向同一个地址)。
三、封装
封装就是方便的使用同一个方法,达到实现既定效果的目的。一般都会采用,将这个共同的方法写在原型中,实例指向的原型是一样的,不会消耗内存
(function() {
/***
* 信息提示组件Toast v1.0
* @param {Object} container 内容容器(必填)
* @param {Object} content 文字内容(可选)
* @param {Object} duration 显示时长(可选)
* 使用方法
* var toast = new Toast("toast", "你好,对话框");
* toast.show();(支持回调函数)
*/
function Toast(container, content, duration) {
this.container = document.getElementById(container);
this.content = content || "这是一段对话";
this.duration = duration || 2000;
}
Toast.prototype.show = function(callback) {
this.callback = callback || function() {};
this.container.style.opacity = 1;
this.container.style.display = "block";
this.container.innerHTML = this.content;
setTimeout(function() {
this.callback && this.callback();
this.hide();
}.bind(this), this.duration);
return this;
}
window.Toast = Toast;
})(window);
四、继承
https://blog.csdn.net/qq_34664239/article/details/83785441
五、闭包
优点:不产生全局变量,实现属性私有化。
缺点:闭包中的数据会常驻内存,在不用的时候要删掉否则会导致内存溢出。
function outFun() {
var num = 10;
function inFun() { // 内部的函数可以使用外部的函数 变量
console.log(num);
}
return inFun; // 注意:不带括号!!不带括号返回函数体,带括号返回函数值
}
var obj = outFun();
// obj = function inFun() { console.log(num)}
obj();
//tab -- 闭包的节流
window.onload = function(){
//要想多个盒子不相互影响 ,我们可以通过id 给他们分开
//封装tab栏切换函数
function tab(obj){
var target = document.getElementById(obj);
var spans = target.getElementsByTagName("span");
var lis = target.getElementsByTagName("li");
for(var i=0;i<spans.length;i++)
{
// spans[i].index = i;
var timer = null;
spans[i].onmouseover = function (num) {
return function(){
clearTimeout(timer);
timer = setTimeout(function(){
for(var j=0; j<spans.length;j++)
{
spans[j].className = "";
lis[j].className = "";
}
spans[num].className = "current";
lis[num].className = "show";
},300)
}
}(i);
spans[i].onmouseout = function() {
clearTimeout(timer);
}
}
}
tab("one");
tab("two");
tab("three");
}