【JavaScript OPP基础】---新手必备
今天和大家分享一下近期整理的有关JavaScriptOOP的基础知识~~~我们一起来学习一下……
JavaScriptOOP基础
一、面向对象编程OOP
1、语言的分类:
面向机器:汇编语言
面向过程:C语言
面向对象:C++,Java,PHP等
2、面向过程和面向对象
①面向过程:专注于如何去解决一个问题的过程。
编程特点:用一个个函数去实现过程操作,没有类和对象的概念;
②面向对象:专注于有哪一个对象实体去解决这个问题。
编程特点是:出现了一个个的类,由类去生成对象。
二、面向对象的三大特征
继承,封装,多态
三、类&对象的关系
1、类:一群有相同特征(属性)和行为(方法)的集合
eg: 人类
属性:"身高,体重,年龄"
方法:"吃饭,睡觉,敲代码"
2、对象:从类中,new出的具有确定属性值和方法的个体称为对象。
eg:张三:属性:身高:身高178,体重150 方法:说话---我叫张三
3、类和对象的关系:
类是抽象的,对象是具体的。
(!类是对象的抽象化,对象是类的具体化!)
通俗的来讲:
类是一个抽象概念,表示具有相同属性和行为的集合。
但是类仅仅表示表明这类群体具有相同的属性,但是没有具体的属性值。
而对象是对类的属性进行具体赋值后,而得到的一个具体的个体;
eg:人类有身高体重年龄,但不能具体说人类的身高体重具体是多少;而张三是人类的一个具体个体,身高体重等有具体值,则张三就是人类的一个对象。
4、使用类和对象的步骤:
①创建一个类(构造函数):
类名,必须要每个单词首字母都大写
function 类名(属性一){
this.属性 = 属性一;
this.方法= function(){}
//this指向谁?即将调用当前构造函数的对象。
}
②通过类,实例化出一个新的对象;
var obj = new 类名(属性一Value);
//原构造函数中this,指向新创建的obj对象
obj.方法();调用方法
obj.属性();调用属性
实例化对象的时候,会执行构造函数
5、两个重要属性:
constructor:返回当前对象的构造函数。(只有对象才有,返回的是构造函数-类)
>>>zhangsan.constructor == Person
>>>对象的constructor,位于_proto_原型对象上(后续讲解)
instanceof:判断对象是否是某个类的实例
>>>zhangsan instanceof Person true
>>>zhangsan instanceof Object true
>>>Person instanceof Object true(函数也是对象)
6、广义对象与狭义对象:
广义对象:除了用字面量声明的基本数据类型之外,外物皆对象,换句话说,能够添加属性和方法的变量,就是对象;
var s = "1" ; 不是对象
var s = new String("1") ; 就是对象
狭义对象:只有属性,方法,除此之外没有任何东西。
var obj = {}; var obj = new Object();
成员属性与成员方法
一、成员属性与成员方法
1、在构造函数中通过this.属性声明;或者实例化出对象后,通过"对象.属性"追加的。
都属于成员属性,或成员方法;也叫实例属性与实例方法。
成员属性/方法,是属于实例化出的这个对象。
通过"对象.属性"调用
二、静态属性与静态方法
2、通过"类名.属性名","类名.方法名"声明的变量,称为静态属性,静态方法;也叫类属性、类方法。
类属性/类方法,是属于类的(属于构造函数的)
通过"类名.属性名"调用
3、成员属性,是属于实例化出的对象的,会出现在新对象的属性上
静态属性,是属于类(构造函数)自己的,不会出现在新对象的属性上
4、JS对象属性的删除:
①对象无需手动删除,JS
②删除对象的属性:delete 对象名.属性名
5、对象是引用数据类型
也就是说,当new出一个对象时,这个obj变量存储的实际上是对象的地址,在对象赋值时,赋的也是地址。
function Person(){}
var xiaoxi = new Person();//xiaoxi对象实际上存的是地址
var ashu = xiaoxi;//赋值时,实际是将xiaoxi存的地址给了ashu
ashu.name = "阿树";//阿树通过地址,修改了地址
console.log(xiaoxi.name);//xiaoxi再通过地址打开对象,实际已经变了
引用数据类型,赋值时传递的是引用(地址)---快捷方式
基本数据类型,赋值时传递的是数据(值)
三、私有属性和私有方法
6、在构造函数中,通过var声明的属性,成为私有属性:
function Person(){var num=1;}
私有属性的作用域,仅在当前函数有效。对外不公开,即通过对象/类都无法调用到。
原型与原型链
【__proto__与prototype】
1、prototype(函数的原型):函数才有prototype。
prototype是一个对象,指向了当前构造函数的引用地址。
2、__proto__(对象的原型对象):所有对象都有__proto__属性。当用构造函数实例化(new)一个对象时,
会将新对象的__proto__属性,指向构造函数的prototype。
eg:zhangsan.__proto__==Person.prototype √
所有对象最终都会指向Object()的prototype。
【原型链】
1、通过构造函数,new出的对象,新对象的__proto__指向构造函数的prototype。
2、所有函数的__proto__指向Function()的prototype。
3、非构造函数new出的对象({} new Object() 对象的prototype)的__proto__指向Object的prototype。
4、Object的__proto__指向Null。
原型属性与原型方法
【类中属性与方法的声明方式】
1、成员属性、成员方法:
this.name = ""; this.func = function(){}
>>>属于实例化出的对象的。通过"对象.属性"调用。
2、静态属性、静态方法:
Person.name = ""; Person.func = function(){}
>>>属于类(构造函数)的。通过"类名.属性"调用。
3、私有属性、私有方法:
在构造函数中,使用var num = 1;声明
>>>只在构造函数内部能用,在外部无法通过任何方式访问。
4、原型属性、原型方法:
Person.prototype.name = "";
Person.prototype.func = function(){};
>>>写在了构造函数的prototype上,当使用构造函数实例化对象时,该属性方法会进入新对象的__proto__上。
也就是说,1/4使用对象可访问,2使用类名可访问,3只能在函数的{}内使用。
5、习惯上,我们会将属性写为成员属性,而方法写为原型方法;
eg:
function Person(){
this.name = "zhangsan";
}
Person.prototype.say = function(){}
原因:
①实例化出对象后,所有属性直接在对象上,所有方法都在__proto__上,非常直观清晰。
②方法写到prototype上,要更加节省内存。
③使用for in 循环时,会将对象以及对象原型链上的所有属性和方法打印出来,而方法往往是不需要展示的。
将方法写到__proto__上,可以使用hasOwnProperty将原型上的方法更好的过滤。
④官方都这么写。
6、当访问对象的属性/方法时,会优先使用对象自有的属性和方法。
如果没有找到,便使用__proto__属性在原型上查找,如果找到即可使用。
但是,当对象自身,以及__proto__上有同名方法,执行对象自身的。
7、可以通过prototype扩展内置函数的相关方法。
代码演示:
function Person(){
this.name1 = "name1"; //成员属性
this.age = "age1";
this.sex = "男";
this.say = function(){
alert("我是大帅哥!");
}
var name2 = "name2";//私有属性
}
Person.name3 = "name3";//静态属性
Person.prototype.name4 = "name4";//原型属性 Person.prototype.say = function(){
alert("我叫"+this.name1);
} var zhangsan = new Person();
// zhangsan.say = function(){
// alert("我是大帅哥!");
// }
zhangsan.say();
zhangsan.toString(); console.log(zhangsan); // console.log(zhangsan.name1);
// console.log(zhangsan.name2);
// console.log(zhangsan.name3);
// console.log(zhangsan.name4);
//
// console.log(s);
可以通过prototype扩展内置函数的相关方法
代码演示:
Number.prototype.add = function(a){
return this+a
} var num = new Number(10);
console.log(num);
alert(num.add(3)); /*
* 为Array类添加一个find(val)方法,当一个Array对象调用该方法的时候,如果能找到val值,则返回其下标,否则返回-1。
*/
Array.prototype.find = function(val){
for (var i = 0; i<this.length;i++) {
if(this[i]==val){
return i;
}
}
return -1;
}
var arr = new Array(1,2,3,4,5);
alert(arr.find(1));
位String类添加一个字符串反转方法
String.prototype.fanzhuan = function(){
var arr = this.split("");
arr.reverse();
return arr.join("")
} console.log(str.fanzhuan()); for-in循环 【for-in循环】
for-in循环,主要用于遍历对象。
for()中格式:for(keys in obj){} keys表示obj对象的每一个键值对的键,所以{}中,使用obj[keys]读取每个值;
但是,使用for-in循环,不但能遍历对象本身的属性和方法。还能够遍历对象原型链上的所有属性和方法。 可以使用hasOwnProperty判断一个属性,是否是对象自身的属性。
obj.hasOwnProperty(keys)==true 表示:keys是对象自身的一个属性 代码演示:
// foreach
function Person(){
this.name1 = "name11111"; //成员属性
this.age = "age11111";
this.func2 = function(){
console.log("thisFun")
}
}
Person.name3 = "name333333";
Person.prototype.name4 = "name44444";
Person.prototype.func1 = function(){
console.log("prototypeFun")
}
var zhangsan = new Person();
for(keys in zhangsan){
if(zhangsan.hasOwnProperty(keys)){ //过滤掉原型上的属性,只打印对象自身属性
console.log(zhangsan[keys])
}
}
JS OOP 中的继承【JS模式实现继承的三种方式】
【文档注释】第一行两个星号
/**
* ……
*/
调用函数时,可以看到注释内容
【JS OOP 中的继承】
1、使用一个子类继承另一个父类,子类可以自动拥有父类的属性和方法。
>>>继承的两方,发生在两个类之间。
2、JS模式实现继承的三种方式:
1)扩展Object实现继承
①定义父类:function Parent(){}
②定义子类:function Son(){}
③通过原型给Object对象添加一个扩展方法。
Object.prototype.customExtend = function(parObj){
for(var i in parObj){
//通过for-in循环,把父类的所有属性方法,赋值给自己。
this[i] = ParObj[i];
}
}
④子类对象调用扩展方法
son.customExtend(Parent);
2)使用call和apply
首先,了解一下call和apply:通过函数名调用方法,强行将函数中的this指向某个对象;
call写法:func.call(func的this指向的obj,参数1,参数2...);
apply写法:func.apply(func的this指向的obj,[参数1,参数2...]);
call与apply的唯一区别:在于接收func函数的参数方式不同。call采用直接写多个参数的方式,而apply采用是一个数组封装所有参数。
①定义父类 funtion Parent(){}
②定义子类 function Son(){}
③在子类中通过call方法或者apply方法去调用父类。
function Son(){
Parent.call(this,....);
}
3)使用原型继承
①定义父类function Parent(){}
②定义子类function Son(){}
③把在子类对象的原型对象声明为父类的实例。
Son.prototype = new Parent();
闭包
【JS中的作用域】
1、全局变量:函数外声明的变量
局部变量:函数内声明的变量
在JS中,函数为唯一的局部作用域,而if、for等其他{}没有自己的作用域
所以,函数外不能访问局部变量。
其实,变量在函数执行完毕以后,占用的内存就被释放。
2、如何访问函数私有变量?
JS中,提供了一种"闭包"的概念:在函数内部,定义一个子函数,可以用子函数访问父函数的私有变量。执行完操作以后,将子函数通过return返回。
function func2(){
var num = 1;
function func3(){
var sum = num+10;
alert(sum);
}
return func3;
}
var f = func2();
f();
3、闭包的作用:
① 访问函数的私有变量;
② 让函数的变量始终存在于内存中,而不被释放。
代码演示:
function func1(){
var n = 1;
}
if(true){
var m = 3;
}
//alert(m); // 3
func1();
//alert(n);// 报错。函数外不能访问局部变量。其实,n变量在func1函数执行完毕以后,占用的内存就被释放。 /*闭包*/
function func2(){
var num = 1;
function func3(){
var sum = num+10;
alert(sum);
}
return func3;
}
var f = func2();
f(); // 循环转一次,创建一个lis[i].onclick函数。但是,当点击li执行函数的时候,i已经变为6,所以无论点击哪一个,i都是6
// 循环创建lis[i].onclick的时候, 循环一次,li[i]里面的i都被赋为不同值;创建了 li[1] li[2] li[3]...
// 但是,创建过程中,并没有执行onlick后面的函数,所以函数里面的i并没有赋值,还是字母i。
// 最终,我们点击li[1] li[2]...时,onclick函数里面的i才会赋值。(但此时,全局变量的i ,已经成为6 了)
var lis = document.getElementsByTagName("li");
for (var i=0;i<lis.length;i++) {
lis[i].onclick = function(){
//alert("您/点击了第"+i+"个li!");
//console.log(lis[i]);
//console.log(this);
}
} // 循环转一次,创建一个自执行函数。
// 而自执行函数拥有自己的作用域,所以用函数局部作用域j保存当前的全局变量i值。这样,创建第一个自执行函数,它的j=1;创建第二个,它的j=2...不同函数的j互不干扰。
// 这样,循环转完以后,相当于创建了6个自执行函数,每个函数中都有一个不同的j变量
var lis = document.getElementsByTagName("li");
for (var i=0;i<lis.length;i++) {
!function(){
var j = i;
lis[j].onclick = function(){
alert("您/点击了第"+j+"个li!");
//console.log(lis[i]);
//console.log(this);
}
}();
} var lis = document.getElementsByTagName("li");
for (var i=0;i<lis.length;i++) {
!function(j){
lis[j].onclick = function(){
alert("您/点击了第"+j+"个li!");
//console.log(lis[i]);
//console.log(this);
}
}(i);
}
【JavaScript OPP基础】---新手必备的更多相关文章
- [新手必备]Python 基础入门必学知识点笔记
Python 作为近几年越来越流行的语言,吸引了大量的学员开始学习,为了方便新手小白在学习过程中,更加快捷方便的查漏补缺.根据网上各种乱七八糟的资料以及实验楼的 Python 基础内容整理了一份极度适 ...
- Android基础新手教程——1.2.1 使用Eclipse + ADT + SDK开发Android APP
Android基础新手教程--1.2.1 使用Eclipse + ADT + SDK开发Android APP 标签(空格分隔): Android基础新手教程 1.前言 这里我们有两条路能够选,直接使 ...
- Android基础新手教程——1.2 开发环境搭建
Android基础新手教程--1.2 开发环境搭建 标签: Android基础新手教程 如今主流的Android开发环境有: ①Eclipse + ADT + SDK ②Android Studio ...
- JavaScript RegExp 基础详谈
前言: 正则对于一个码农来说是最基础的了,而且在博客园中,发表关于讲解正则表达式的技术文章,更是数不胜数,各有各的优点,但是就是这种很基础的东西,如果我们不去真正仔细研究.学习.掌握,而是抱着需要的时 ...
- JavaScript学习基础部分
JavaScript学习基础 一.简介 1.JavaScript 是因特网上最流行的脚本语言,并且可在所有主要的浏览器中运行,比方说 Internet Explorer. Mozilla.Firefo ...
- JavaScript入门基础
JavaScript基本语法 1.运算符 运算符就是完成操作的一系列符号,它有七类: 赋值运算符(=,+=,-=,*=,/=,%=,<<=,>>=,|=,&=).算术运 ...
- JavaScript 语言基础知识点总结(思维导图)
JavaScript 数组 JavaScript 函数基础 Javascript 运算符 JavaScript 流程控制 JavaScript 正则表达式 JavaScript 字符串函数 JavaS ...
- JavaScript语言基础知识点图示(转)
一位牛人归纳的JavaScript 语言基础知识点图示. 1.JavaScript 数据类型 2.JavaScript 变量 3.Javascript 运算符 4.JavaScript 数组 5.Ja ...
- JavaScript 语言基础知识点总结
网上找到的一份JavaScript 语言基础知识点总结,还不错,挺全面的. (来自:http://t.cn/zjbXMmi @刘巍峰 分享 )
随机推荐
- H5_background-clip(css3——裁剪)
利用background-clip实现此效果 在body里面只需要写:<div class="box"></div> 在样式里面写上: .box{ widt ...
- Mac 自定义sublime在浏览器中打开的快捷键/win系统理论通用
安装"view in browser"官方版的说明:(前提是得先安装package control插件) 1.通过"ctrl+shift+p"打开命令面板 2. ...
- SpringMVC基础学习(三)—参数绑定
一.基本数据类型的绑定 页面 <form action="${pageContext.request.contextPath}/test.do" method="p ...
- 封装Echarts
项目中需要对数据进行图形展示,例如展示柱状图.饼状图等.这类的前端展示脚本很多,常见的是HighCharts和Echarts.HighCharts是基于svg技术的,而echarts基于Echarts ...
- 浅谈访问控制列表(ACL)
1.ACL简介2.前期准备3.ACL的基本操作:添加和修改4.ACL的其他功能:删除和覆盖5.目录的默认ACL6.备份和恢复ACL7.结束语 1.ACL简介 用户权限管理始终是Linux系统管理中最重 ...
- 【Azure】Azure学习方法和学习资料
学习方法: DEX为入门培训,fundamental book进阶材料,Azure 官方为补充权威材料,网站一些大拿的Blog是很多实践精华,推荐阅读. 推荐教材和学习内容: EDX培训:http:/ ...
- c++:自己动手实现线程安全的c++单例类
前段时间使用c++做项目开发,需要根据根据配置文件路径加载全局配置文件,并对外提供唯一访问点.面对这样一个需求,自然的就想到了使用单例模式来创建一个单例配置对象,供外部调用.一开始想使用boost中自 ...
- angular 过滤排序
<table class="table"> <thead> <tr> <th ng-click="changeOrder('id ...
- 简单聊聊Storm的流分组策略
简单聊聊Storm的流分组策略 首先我要强调的是,Storm的分组策略对结果有着直接的影响,不同的分组的结果一定是不一样的.其次,不同的分组策略对资源的利用也是有着非常大的不同,本文主要讲一讲loca ...
- Cf #353 D. Tree Construction
题目链接:http://codeforces.com/problemset/problem/675/D 题目大意是将一个没有相同数字的数列中的数字依次插入到二叉搜索树中,问除了第一个数字以外,其他数字 ...