javascript面向对象的写法03
javascript面向对象的写法03
js一些基础知识的说明
prototype
console.log(String.prototype);
console.log(Date.prototype);
console.log(Object.prototype); function ClassA(name,job,born) {
}
console.log(ClassA.prototype);
prototype一般作用
Object.prototype.name = "111"; //为Object原型增加一个name属性
function ClassA(name,job,born) {
} ClassA.prototype.name = "123"; //自定义类原型也可以修改
ClassA.prototype.func1 = function(){}; //同样可以修改原型的func1属性为一个函数指针
prototype作用可以扩展类,比如为某个类的原型增加了一些属性,那么该修改过的类所创建的所有对象都有此属性。
function ClassA(name,job,born) {
//此时的ClassA类没有定义任何的属性,用它new出来的对象自然是没有name属性
}
var objB = new ClassA();
console.log(objB.name); //输出undefined
Object.prototype.name = "111";
ClassA.prototype.name = "123"; //prototype的修改对之前new出来的对象同样生效
var objA = new Object();
console.log(objA.name); //内置类的prototype修改也是可以的
console.log(objB.name); //修改过prototype后便有这个属性了
可以把prototype看做类的另外一半,把prototype和原本的类并在一起就相当于一个完整的类了。
function ClassA() {
this.a = 100;
this.b = 100;
}
ClassA.prototype = {
'name': '123',
'getName': function(){}
};
//类似于
function ClassA() {
this.a = 100;
this.b = 100;
this.name = '123';
this.getName = function(){};
}
js访问一个对象的属性时,先在自己的属性中寻找,如果没有继而会去从类的prototype中找。自己定义的属性是会覆盖住类prototype定义的属性。
function ClassA() {
this.a = 100;
}
ClassA.prototype = {
'a': 200,
};
var obj = new ClassA();
console.log(obj.a); //输出100
prototype还可以修改已有的类
Array.prototype.containsObject = function(e) {
for (i=0; i<this.length; i++) {
if (this[i] == e) {
return true;
}
}
return false;
};
使用prototype的好处
function ClassA() {
this.a = 100;
}
ClassA.prototype = {
'b': 200
};
那么两者有何区别呢?使用何种方式好。
function ClassA() {
this.a = 100;
}
//两者等同
function ClassA() {
}
//
var obj = new ClassA();
obj.a = 100;
//也就是如果有其他对象要创建的话就如下面一样
var obj02 = new ClassA();
obj02.a = 100;
var obj03 = new ClassA();
obj03.a = 100;
function ClassA() {
this.func1 = function() {}; //此方法每个类都有一份拷贝。
}
ClassA.prototype.func2 = function(){}; //此方法存在于类的prototype属性中,只有一个地方有。
//调用func2的时候,obj对象自身没有,于是到类的prototype中寻找。
var obj = new ClassA();
obj.func2();
注意这两种写法的区别
function ClassA() {
}
//第一种方式扩展方法
ClassA.prototype.func1 = function() {};
ClassA.prototype.func2 = function() {};
//第二种,注意此种方法会有一些影响
ClassA.prototype = {
"func1": function() {},
"func2": function() {}
};
constructor
function ClassA() {
}
var obj = new ClassA();
console.log(obj.constructor); //这里输出的就是ClassA函数,也就是ClassA类了。
console.log(ClassA.constructor); //类(函数)也是对象,也有constructor。它的是Function
原型对象和原型链
function ClassA() {
}
var obj = new ClassA();
//obj的原型对象是什么? 是obj构造函数的prototype属性所指向的对象
obj.constructor == obj构造函数
obj.constructor.prototype == obj构造函数的prototype属性所指向的对象 == obj的原型对象
function ClassA() {
}
//ClassA是对象,它的原型对象是什么?
ClassA.prototype != ClassA的原型对象
ClassA.constructor.prototype == ClassA的原型对象
obj.constructor.prototype.constructor.prototype //错误
obj.constructor.constructor.prototype //正确
对象靠内部的__proto__属性和原型对象关联。每个对象有个__proto__属性,此属性名字前有下划线就表明他是个内部变量,外部不可访问更加不能修改。
obj.__proto__ == obj.constructor.prototype == obj的原型对象
call和apply方法
最简单,call方法会执行一个函数。但是与简单的函数执行有点不同,下面会提到。
//最简单的使用call,调用一个普通的函数
function func1() {
console.log(func1);
}
func1.call();
call如果带参数则情况不同,call函数的第一个参数有特殊意义,它会将第一个参数传给被调用的函数里面,并且将被调函数里面的this指针切换到这个参数。
function func1() {
console.log(this); //这种情况下,这里的this指向的是下面的a。因为下面使用func1.call调用并传递了第一个参数a。
}
var a = {'b': 100};
func1.call(a); //func1函数会被执行,并且对象a会被传递到func1中,作为func1中this的执行。
如果call没有第一个参数,则默认传递window对象。
看一个稍微复杂点的例子,如果能明白各个方法的调用情况就对call理解了。
function A() {
this.bb = function(){
console.log(this);
};
}
function ClassA() {
console.log(this);
this.bb(); //注意ClassA本身没有bb这个方法。
}
var a = new A();
a.bb.call(); //调用a.bb方法。因为没有第一个参数,则传递window到a.bb方法中,所以a.bb里面的this指针指向的是window
ClassA.call(a); //调用ClassA函数,ClassA里面的this指针指向的是a对象。所以this有bb方法可以调用。
看下面的例子,因为call可以替换函数内的this对象,则可以达到如下效果。
function A() {
this.attr = 100;
this.func = function(){
};
}
function B() {
A.call(this);
}
var b = new B();
b.func();
console.log(b.attr);
function func(a, b, c, d) {
}
func.call(obj, 1, 2, 3, 4);
func.apply(obj, [1, 2, 3, 4]); //第二个参数必须是一个数组。数组里面内容依次是调用func的实参。
除了参数格式外,其他没啥区别。但是因为参数格式不同,所以apply函数可以实现简化代码的作用。例如
function A(a, b, c) {
}
function B(a, b, c) {
A.apply(this, arguments); //这里arguments为[1,2,3]。所以就直接传递了,不用自己组装。
}
var a = new B(1, 2, 3);
new操作符
function a(){}
var b = a(); //当做普通函数对待,此时b的值为undefine
var b2 = new a(); //此时b2为一个对象,一个object空对象,没有什么其他自定义的属性。
new内部执行的一些操作
aa.__proto__ = Class.prototype; //前面提到过,对象通过__proto__属性和原型对象关联。
3.执行constructor函数并且设置aa的constructor属性。前面提到过constructor指向的是构造函数(类),constructor函数执行过程中,函数内部会创建一个this指针,this指向到第一步创建的对象中。这样constructor构造函数内部就可以使用this关键字了。
constructor.apply(aa, [args]); //执行apply方法,传递第一步的对象为第一个参数,则后面的this就是指向的aa.
4.将第一步创建的aa对象,或者说是this指向的对象返回。如果构建函数本身有返回值,则情况会有所不同。
4.1普通情况下返回第一步创建的对象
function ClassA() {
this.a = 100;
}
function ClassA() {
this.a = 100;
return {
"b": 200
};
}
var obj1 = new ClassA();
var obj2 = ClassA(); //此种情况下,ClassA被当作普通函数执行,它里面的this指针指向是全局的对象window
上面此种情况用new操作符和直接执行函数返回的结果是一样的。都是{"b": 200}对象。使用new关键字的情况,前面几个步骤创建的对象会抛弃。
function ClassA() {
this.a = 100;
return 200; //因为是返回的200是简单类型,所以在使用new ClassA()的情况,此语句可以看做是被忽略了。
}
new关键字做的工作看以看似下面的几条语句
var obj = {};
obj.__proto__ = constructor.prototype;
constructor.apply(obj, [args]);
javascript面向对象的写法03的更多相关文章
- javascript面向对象的写法及jQuery面向对象的写法
文章由来:jQuery源码学习时的总结 在JS中,一般的面向对象的写法如下: function Cao(){}//定义一个构造函数 Cao.prototype.init = function(){}/ ...
- javascript面向对象的写法01
类和对象 其他面向对象的语言类的语法是内置的,自然而然的事.javascript中有对象,但没有类的语法,类的实现需要模拟出来. 只需要把对象想成一个容器,里面存放一些属性或方法,把类想象成一个对象的 ...
- javascript面向对象的写法02
面向对象特性的初步实现 1.封装 利用作用域封装变量 作用域的概念是一样的,for语句,if语句等这些作用域内定义的变量只能作用域内访问,函数内定义的变量只能函数内访问. function Class ...
- [js高手之路] javascript面向对象写法与应用
一.什么是对象? 对象是n个属性和方法组成的集合,如js内置的document, Date, Regexp, Math等等 document就是有很多的属性和方法, 如:getElementById, ...
- 03.JavaScript 面向对象精要--理解对象
JavaScript 面向对象精要--理解对象 尽管JavaScript里有大量内建引用类型,很可能你还是会频繁的创建自己的对象.JavaScript中的对象是动态的. 一.定义属性 当一个属性第1次 ...
- 浅谈javascript面向对象
我们常用的两种编程模式 POP--面向过程编程(Process-oriented programming) 面向过程编程是以功能为中心来进行思考和组织的一种编程方法,它强调的是系统的数据被加工和处理的 ...
- Javascript面向对象(封装、继承)
Javascript 面向对象编程(一):封装 作者:阮一峰 Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象.但是,它又不是一种真正的面向对象编程( ...
- javascript面向对象(一):封装
本文来自阮一峰 学习Javascript,最难的地方是什么? 我觉得,Object(对象)最难.因为Javascript的Object模型很独特,和其他语言都不一样,初学者不容易掌握. 下面就是我的学 ...
- JavaScript面向对象,及面向对象的特点,和如何构造函数
1.面向对象和面向过程的区别 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了: 面向对象是把构成问题事务分解成各个对象,建立对象的目的不是 ...
随机推荐
- 分分钟钟学会Python - 数据类型(int、bool、str)
第三天学习内容 今日内容 1.整型(int) 2.布尔类型(bool) 3.字符串(str) 内容详细 1.整型 Python中的整型用int表示. 1.python2中: 在32位机器上,整数的位数 ...
- jieba和文本词频统计
---恢复内容开始--- 一.结巴中文分词涉及到的算法包括: (1) 基于Trie树结构实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图(DAG): (2) 采用了动态规划查找最大 ...
- Cloudera Manager安装之Cloudera Manager安装前准备(Ubuntu14.04)(一)
其实,基本思路跟如下差不多,我就不多详细说了,贴出主要图. 博主,我是直接借鉴下面这位博主,来进行安装的!(灰常感谢他们!) 在线和离线安装Cloudera CDH 5.6.0 Cloudera M ...
- 028-applicationContext.xml配置文件
版本一 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http: ...
- php 内存共享shmop源码阅读
多进程通信的时候,会涉及到共享内存.shmop_open()创建或打开一个内存块 PHP_FUNCTION(shmop_open) { long key, mode, size; struct php ...
- STM32F407 使用HAL库延时微妙实现方法(附CubeMX配置过程)
STM32F407 使用HAL库延时微妙实现方法(STM32CubeMX配置) 作者 : 李剀出处 : https://www.cnblogs.com/kevin-nancy/p/10696681.h ...
- [springBoot系列]--spring-boot-devtools在Idea中热部署方法
1 pom.xml文件 注:热部署功能spring-boot-1.3开始有的 <!--添加依赖--> <dependency> <groupId>org.sprin ...
- 深入理解JavaScript系列(39):设计模式之适配器模式
介绍 适配器模式(Adapter)是将一个类(对象)的接口(方法或属性)转化成客户希望的另外一个接口(方法或属性),适配器模式使得原本由于接口不兼容而不能一起工作的那些类(对象)可以一些工作.速成包装 ...
- 深入理解JavaScript系列(40):设计模式之组合模式
介绍 组合模式(Composite)将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性. 常见的场景有asp.net里的控件机制(即control ...
- [转]Work With Odata in Web API: Create Your First Odata Service
本文转自:http://www.c-sharpcorner.com/UploadFile/dacca2/work-with-odata-in-web-api-create-your-first-oda ...