问题1: OOP 指什么?有哪些特性
- OOP:
“面向对象编程”(Object Oriented Programming)是目前主流的编程范式。Java,JavaScript,C#,C+ +,Python,PHP,Ruby和Objective-C)都支持面向对象编程。它的核心思想是将真实世界中各种复杂的关系,抽象为一个个对象,然后由对象之间的分工与合作,完成对真实世界的模拟。每个对象都可以被看作是一个拥有清晰角色或责任的独立小机器。
“传统的过程式编程”(procedural programming)由一系列函数或一系列指令组成,而面向对象编程的程序由一系列对象组成。每一个对象都是功能中心,具有明确分工,可以完成接受信息、处理数据、发出信息等任务。因此,面向对象编程具有灵活性、代码的可重用性、模块性等特点,容易维护和开发,非常适合多人合作的大型软件项目。 - 特性:
封装性,继承性,多态性
var Person = function (name){
this.name = name;
}
Person.prototype.sayHello = function(){
console.log('hello');
}
var ethan = new Person('ethan');
ethan.sayHello();
var Man=function(){
this.sex="man";
}
Man.prototype.sayHello=function(){
console.log("hi");
}
var man1=new Man();
man1.sayHello();
//封装性:把相对应的变量和方法封装到一起
//继承性:ethan实例对象本身没有定义sayHello,但是由于ethan是构造函数Person的实例,继承Person存放在prototype对象中的共有属性和方法,所以可以调用sayHello。
//多态性:同一个方法可以有不同的表现。比如通过new两个实例,可以分别对里面的方法函数扩展,得到的结果不同,但是,这都属于同一个方法。
问题2: 如何通过构造函数的方式创建一个拥有属性和方法的对象?
function People(name,age){
this.name = name
this.age = age
this.sayName = function(){
console.log(this.name)
}
}
var p = new People('hunger','20')
p.sayName() //hunger
问题3: prototype 是什么?有什么特性
JavaScript 的每个对象都继承另一个对象,后者称为“原型”(prototype)对象。只有null除外,它没有自己的原型对象。
原型对象上的所有属性和方法,都能被派生对象共享。这就是 JavaScript 继承机制的基本设计。
通过构造函数生成实例对象时,会自动为实例对象分配原型对象。每一个构造函数都有一个prototype属性,这个属性就是实例对象的原型对象。
var Person = function (name){
this.name = name;
}
Person.prototype.sayHello = function(){
console.log('hello');
}
var ethan = new Person('ethan');
ethan.sayHello();
//其中Person的prototype对象,就是ethan的原型对象。ethan.sayHello先在实例当中找方法,若没找到,就去prototype对象中找。
ethan.sayHello=function(){
console.log("hi");
}
ethan.sayHello();
//因为ethan实例当中已经有sayHello方法,所以不会再去原型上找方法
问题4:画出如下代码的原型图
function People (name){
this.name = name;
this.sayName = function(){
console.log('my name is:' + this.name);
}
}
People.prototype.walk = function(){
console.log(this.name + ' is walking');
}
var p1 = new People('饥人谷');
var p2 = new People('前端');
问题5: 创建一个 Car 对象,拥有属性name、color、status;拥有方法run,stop,getStatus
function Car(name,color,status){
this.init(name,color,status);
thsi.bind();
}
Car.prototype.init=function(name,color,status){
this.name=name;
this.color=color;
this.status=status;
}
Car.prototype.bind=function(){
this.run=function(){...};
this.stop=function(){...};
this.getStatus=function(){...};
}
问题6: 创建一个 GoTop 对象,当 new 一个 GotTop 对象则会在页面上创建一个回到顶部的元素,点击页面滚动到顶部。拥有以下属性和方法
1. `ct`属性,GoTop 对应的 DOM 元素的容器
2. `target`属性, GoTop 对应的 DOM 元素
3. `bindEvent` 方法, 用于绑定事件
4 `createNode` 方法, 用于在容器内创建节点
代码
问题7: 使用木桶布局实现一个图片墙
代码
笔记:
1、 面向对象的初心
- 目的
1、改善可读性
screenprint();
Screen.print();
2、提升重用性
2、原则:开放封闭原则
1、对于扩展是开放的(open for extension)。当应用的需求改变时,可以对模块进行扩展,使其满足改变的新行为。
2、 对于修改是关闭的(close for modification)。对模块进行扩展时,不必改变模块的源代码。
3、三要素:封装,继承,多态
1、封装:把很多个属性和方法封装到一个对象当中
2、继承:继承一个对象的所有的属性和方法
3、多态:不同的对象对同一个方法有不同的表现
4、实例化对象
var object=new Object();
2、 new操作
var object=new Object()时,都发生了什么?
1、创建了一个空对象作为this
2、this.proto指向构造函数的prototype
3、运行构造函数
4、返回this(如果构造函数里没有return,若存在return引用类型,则返回return后的值)
var Foo=function(){
this.name="foo";
}
var foo=new Foo();
console.log(foo); //console.log(),console对象时,先展示对象的构造函数
//发生了什么?
1、创建了{},this指向{}
2、{}._proto_指向了Foo.prototype
3、执行构造函数,{}.name="foo"
4、返回{}
var Foo=function(){
this.name="foo";
return {name:"foo1"};
}
var foo=new Foo();
console.log(foo); //console.log(),console对象时,先展示对象的构造函数
//发生了什么?
1、创建了{},this指向{}
2、{}._proto_指向了Foo.prototype
3、执行构造函数,{}.name="foo"
4、返回{name:"foo1"}
3、如何手动指定对象原型
//第一种:
var obj._proto_={...}; //ES6方法支持._proto_属性,IE低版本不支持
//第二种:
var my={
name:"foo"
}
var obj={};
var Temp=functon(){};
Temp.prototype=my;
obj=new Temp(); //此时的constructor指向的是Temp
obj.constructor=my;
var Animal=function(){
this.种类="动物";
}
Animal.prototype.say=function(){
console.log(this.种类+"叫");
}
var animal=new Animal();
animal.say();
var Cat=function(){
Animal.apply(this,arguments);
this.tail="一条尾巴";
}
//下面三句是为了实现:Cat.prototype._proto_=Animal.prototype;只是Cat.prototype._proto_为ES6,IE低版本不支持
var F=function(){}; //创建新的对象
F.prototype=Animal.prototype; //将新对象的prototype指向Animal
Cat.prototype=new F(); //让Cat.prototype的_proto_指向F的prototype,此时的Cat也是一个构造函数,因为不是Cat=new F();
var cat=new Cat();
cat.constructor==Animal //true,表示cat的构造函数是Animal
Cat.prototype.constructor=Cat; //把构造函数指向Cat
4、不用类实现继承
var animal={
"种类":"动物",
say:function(){
console.log("叫");
}
}
var cat=extend(animal); //使用任意手段让cat._proto_指向animal
function extend(parent){
var Temp=function(){};
Temp.prototype=parent;
return new Temp;
}
cat.tail="一条尾巴";
cat.say=function(){
console.log("喵喵喵");
}
5、代码封装的演变
- 把代码用对象包住,避免全局污染
缺点:只在当前页面对一个代码实现功能,要在当前页面的两个地方实现代码,慎用
var Tab={
init: function(){ //把变量全部放到init方法中,并设置初始值。
this.name="Ethan";
this.bind(); //执行bind方法
}
bind: function(){
this.name //调用name变量要在前面加上this,并确保this指的是Tab
var self=this; //若this的指向会变,那在改变前先把当前this进行保存,在进行引用
self.name;
}
}
Tab.init();
- 通过new方法创建独立的对象
优点:可以对功能进行重复使用,缺点:构造函数里的方法重复创建
function Tab(tagName){
this.init=function(tagName){
this.name="Ethan";
}
this.bind=function(){
this.name //调用name变量要在前面加上this,并确保this指的是Tab
var self=this; //若this的指向会变,那在改变前先把当前this进行保存,在进行引用
self.name;
}
this.init(tagName);
this.bind(); //执行bind方法
}
var tagName1=document.getElementsByClassName("class1")[0];
var tagName2=document.getElementsByClassName("class2")[0];
new Tag(tagName1);
new Tag(tagName2);
- 给new方法创建的对象设立原型
优点:把方法全部放进原型当中,使用new方法时创建的实例就不会再创建方法,直接从原型链中找,节省了空间
function Tab(tagName){
this.init(tagName);
this.bind(); //执行bind方法
}
Tab.prototype.init=function(tagName){
this.name="Ethan";
}
Tab.prototype.bind=function(){
this.name //调用name变量要在前面加上this,并确保this指的是Tab
var self=this; //若this的指向会变,那在改变前先把当前this进行保存,在进行引用
self.name;
}
var tagName1=document.getElementsByClassName("class1")[0];
var tagName2=document.getElementsByClassName("class2")[0];
new Tag(tagName1);
new Tag(tagName2);