一、面向过程和面向对象的区别、联系
1.面向过程编程:注重解决问题的步骤,分析问题需要的每一步,实现函数依次调用。
2.面向对象编程:注重问题中的对象,分析问题中对象的联系,实现对象间的通讯解决问题.面向对象编程淡化过程,强调对象 更贴近我们人日常处理问题的方式。
3.面向过程:所有功能都是在需要使用的时候才开发,相当于去餐馆点菜,现点现做,需要等。
4.面向对象:在正式开发之前,就先把所有需要使用的功能都开发好,并以属性或者方法的形式存放
在一个对象中,在实际开发的时候根据需要来调用写好的功能。相当于去快餐店吃快餐,菜都是
事先已经炒好的,去了就可以吃。
二、什么是对象?什么是面向对象?
1.对象是类的实例。对象是具体的事物。
2.只有对象才有属性和方法,基本数据类型没有,string等类型能够使用的方法来自他自身的构造器,在基本数据类型调用方法时会临时创建一个对象出来,在方法完成时自动销毁。
3.对象,黑盒子,是一个整体,对外提供一些操作,不了解内部的结构,知道表面的各种操作(按钮)。
4.面向对象简单的来说就是:不了解原理的情况下,会使用功能。面向对象是一种通用思想,并非只有编程中能用,任何事情都可以用。
5.面向对象编程也叫OOP,特点:①抽象,抓住核心问题,把最主要的、跟问题相关的特征抽出来。②封装:不考虑内部实现,只考虑功能使用。简单说:就是看不到里面的东西,用好表面的功能。③继承(遗传):从已有对象上,继承出新的对象。多重继承。多态。从父类上继承出一些方法、属性,子类,又有一些自己的特性。多重继承:可以同时继承多种父级的特性
6.对象的组成:①方法--函数:过程、动态的②属性--变量:状态、静态的。
7.变量和属性的不同:变量是自由的,不属于任何人。属性是有归属的,属于一个对象的。
//定义一个对象
//直接量
//var obj={};
//使用Object声明对象
var obj= new Object();
//覆盖式的定义方式,
var person={
name:"张三",
age:"18",
hobby:function() {
console.log("我喜欢篮球");
}
}
//后面的会覆盖前面的
//var person = {
//name: "李四"
//}
//追加属性和方法
person.height="178cm";
console.log(person)
//调用
person.hobby();
console.log(person.name);
对象数组,一个数组里面有多个对象
var phoneNumber=[{
name:"coco",
tel:"132432432"
}, {
name:"popo",
tel:"5840583"
}]
//取到里面的东西
//console.log(phoneNumber[0].name)
//如果数据比较多,需要用循环
for (var i=0; i<phoneNumber.length;i++){
console.log(phoneNumber[i].name);
}
var person={
name:"张三",
height:"189cm"
}
//获取对象里面的东西,如果数据比较多,也可以循环
//key下标 value值
for(var k in person) {
console.log(k);//对象的下标
console.log(person[k]);//获取单个值
}
三、工厂模式
并不常用,每次调用函数都重新定义了函数,(函数重复,资源浪费)
//工厂模式
function factory(name,age) {//类
var obj={};
obj.name=name;
obj.age=age;
obj.hobby=function() {
console.log("sing");
}
return obj;
}
//直接调用
factory().hobby();//sing
//用参数接收调用
var newFactory=factory("张三","18");//对象
newFactory.hobby();
console.log(newFactory.name);
//不用传参,用arguments,如果参数不确定的情况下,就用arguments
function factory() {
//console.log(arguments);
var obj={};
obj.name=arguments[0];
obj.age=arguments[1];
obj.hobby=function() {
console.log("sing");
}
return obj;
}
四、构造函数
//创建构造函数,类似于类
function Student(name,sex){
//属性
this.name = name;
this.sex = sex;
//方法
this.intro = function(){
alert("姓名:" + this.name + "\n" + "性别:"+this.sex);
}
}
使用构造函数
//创建对象
var student = new Student("张三","男");
//调用方法
student.intro();
构造函数:用来构建对象的函数。
注意:1.为了区别普通函数,构造函数的函数名首字母规定应该为大写。2.构造函数必须使用new运算符来调用执行(实例化对象)。3.在构造函数里面写属性,在原型里面写方法
五、原型
1.通过new实例化出来的对象,其属性和行为来自于两个部分,一部分来自于构造函数,另一部分来自于原型.
2.当我们声明一个类时,其实同时生成了一个对应的原型.例如我们定义Person这个类时,会产生一个与Person类对应的原型prototype.
3.原型本身就是一个对象。
4.通过prototype可以指向这个原型,原型可以通过constructor指向Person类(构造函数).
function Dog(){//构造函数
this.name="大黄";
this.sex="公";
}
Dog.prototype={//原型
bark:function(){
alert("汪汪~");
}
}
//也可以这样写
//通过构造函数找到原型
Car.prototype={
action1:function() {
console.log("我是方法1")
},
action2:function() {
console.log("我是方法2")
},
}
//原型
//Car.prototype.action = function() {
//console.log("我是原型里的方法");
//}
function Person() {
this.arr=[1,2,3];
}
//通过原型可以取到构造函数里面的东西
Person.prototype.hobby=function() {
console.log(this.arr);
}
var newPerson= newPerson();
newPerson.hobby();
六、原型链
1.原型链:原型链是指对象在访问属性或方法时的查找方式。
2.当访问一个对象的属性或方法时,会先在对象自身上查找属性或方法是否存在,如果存在就使用对象自身的属性或方法。如果不存在就去创建对象的构造函数的原型对象中查找 ,依此类推,直到找到为止。如果到顶层对象中还找不到,则返回 undefined。
3.原型链最顶层为 Object 构造函数的 prototype 原型对象,给 Object.prototype 添加属性或方法可以被除 null 和undefined 之外的所有数据类型对象使用。
七、公有和私有
1.在传统的面向对象的语言中一般会提供public、protected、private等关键字来声明属性和方法的
公开性.
2.javascript中没有这些关键字,我们通过作用域来实现公有或者私有。
functionWomen(name,sex){
//公有属性
this.name=name;
this.sex=sex;
//私有属性
var_age="30";
//公有方法
this.eat=function(){
alert("");
}
//私有方法
var fight=function(){
alert("!");
}
}
对于上述例子中,使用this.xxx定义的属性和方法是公有的,我们在外部使用对象很容进行访问.
使用 var xxx定义的属性和方法是私有的.只能在构造函数内部进行直接访问.
set方法:我们可以通过公有的方法去访问私有的属性.我们把给专门给私有属性赋值的方法称为set方法
get方法:我们把专门获取私有属性的方法称为get方法
function Women(name){
this.name=name;
var _age="30";
//set方法
this.setAge=function(age){
_age=age;
}
}
function Women(name){
this.name=name;
var_age="30";
//get方法
this.getAge=function(){
return _age;
}
}
八、继承
1.继承的目的是找到类之间的共性,精简代码。
2.原型不能直接被继承
//解决继承中原型的传址问题
function Dad() {
this.name="杨幂";
this.age=18;
}
Dad.prototype.hobby=function() {
console.log("电视");
}
function Son() {
this.name="小糯米";
Dad.call(this);
}
//创建一个新的对象就会新引用一个地址
Son.prototype= newDad();
Son.prototype.hobby=function() {
console.log("肉肉");
}
var newDad= new Dad();
newDad.hobby();
九、改变this指向
//下面三种方式可以改变this指向
var o={
name:"张三",
age:"18"
}
function test(name,age) {
console.log(this);
}
//这时候this指向window
//test();
//通过call改变函数内部的this指向
//这时候this指向o
//test.call(o)
var o={
name:"张三",
age:"18"
}
function test(name,age) {
console.log("姓名"+name+"年龄"+age)
console.log(this);
}
//test.call(o,"张三",18)
//test.apply(o,["李四",36]);//第二个参数需要的是一个数组
//test.bind(o)("王五", 21);
十、传值和传址
传址:复杂的数据类型就会涉及到传址问题
传值:简单的数据类型,(一个简单的变量就是简单的数据)
//传值
var a=10;
var b=a;
var b=5;
console.log(a)//10
//传址
var arr1=[1,2,3,4];
var arr2=arr1;
arr2[1]=5;
console.log(arr1);//[1,5,3,4]
//传址
var obj1={
name:"coco",
age:18
};
var obj2=obj1;
obj2.age=10;
console.log(obj1)//{name:"coco",age:10}
//传址造成的问题案例
function Dad(height) {
this.name="王健林";
this.height=height;
this.money="$88888888888";
this.hobby=function() {
console.log("太极");
}
}
//js面向对象里面的继承,原型是不会被继承的
Dad.prototype.fun=function() {
console.log("高尔夫");
}
functionSon(height) {
this.name="王思聪";
//继承(就相当于把this指向的函数加到Dad里面)
//Dad.call(this, height);
//Dad.apply(this, [height]);
Dad.bind(this)(height);
}
//解决不能继承原型的问题
//这种方式,造成了两个fun的地址是在一起,改变一个,另一个也会被改变,传址
Son.prototype=Dad.prototype;
Son.prototype.fun=function() {
console.log("泡妞");
}
var newDad= new Dad();
newDad.fun();//泡妞
十一、深拷贝(克隆)
1.JSON.stringify() 将 [] 或 {} 的对象转换成字符串形式的值,就是编码
2.JSON.parse() 将字符串形式的 [] 或 {} 值转换成对象,就是解码
3.克隆实现原理:利用字符串赋值为传值的特点,先将对象转换成字符串形式,然后将字符串形式的值再转换成对象。
4.兼容问题:不支持低版本IE浏览器
//解决传址问题
//深拷贝,克隆
var obj1={
name:"coco",
age:18
};
//编码json数据
//var _json = JSON.stringify(obj1);
//console.log(_json)
//console.log(typeof _json) //string
//解码json串
//var obj2 = JSON.parse(_json);
//console.log(obj2);
//用深拷贝解决传址问题
var obj2=JSON.parse(JSON.stringify(obj1));
obj2.age=13;
console.log(obj1);
十二、typeof的不足
typeof 可以准确地判断出简单数据类型,但对复杂数据类型的判断相对比较模糊。
比如: 数组对象 \ 时间对象 \ 正则对象 \ Math对象等都返回的是 ‘object’。
优化方案:封装函数
function type( obj ){
var o = {};
return o.toString.call(obj).slice(8,-1).toLowerCase();
}
实现原理:Object 对象的 prototype 的 toString() 方法会返回一个表示对象本身类型的字符串。
网友评论