Javascript函数、构造函数、原型、类和对象
函数
函数是JavaScript中特殊的对象,对函数执行typeof运算会返回字符串"function",因为函数也是对象,他们可以拥有属性和方法。
静态方法
函数在JS中定义了类的名字,任何添加到函数的属性都是类字段和类方法(类比Java中类的static variable 和 static method),下面代码起到Java里面static method的效果:
var foo = function(){};
foo.printLog = function(){
if (arguments.length != 0)
{
console.log(Array.prototype.join.call(arguments, " - "));
}
};
foo.printLog("Test", "Static Method");
构造函数
如果函数或者方法的调用之前加上new关键字,他就构成了构造函数的调用.,
构造函数的调用和普通函数,方法的调用在实参处理,调用上下文和返回值方面有不同
(1).实参处理不同
凡是没有形参的构造函数调用都可以省略圆括号
(2)调用上下文的不同
调用构造函数创建一个新的空对象,这个对象继承自构造函数的prototype(原型).构造函数试图初始化这个新对象,并把这个新对象当做构造函数的调用上下文,所以在构造函数中this关键字可以用来引用这个新对象,也就能够在构造函数中初始化这个新对象.
注意: 尽管构造函数看起来像一个方法调用,它依然会使用这个新对象作为调用上下文。也就是说,在表达式new
o.m() 中,调用上下文并不是o.
例子1-2:
function A()
{
this.a = 123;
this.init();
}
A.prototype = {
get: function(){console.log('The value of A is ' + this.a);},
init: function(){
console.log('do init here');
this.a=567;
}
}
var obj = new A;
obj.get();
(3)返回值不同
构造函数通常不使用return关键字调用完毕之后会返回一个对象(就是新创建的这个对象)
this关键字
this是一个关键字,不是变量也不是属性.
this关键字没有作用域的限制,他只有下面几种情况
(1)一个函数被当做方法调用,则函数中的this指向的是调用它的对象
(2)一个函数被当做函数调用,则函数中的this指向的全局对象(非严格模式)或者是undefined(严格模式下)
(3)函数被当做构造函数调用,this就指向构造函数创建的新对象
例子:
var a = {name:'frank',age:30};//创建一个新对象
function A()
{
console.log(this);
}
A.call(a); //对象a的方法调用:this代表对象a,因为通过call的调用上下文是a
A();//全局函数调用:this代表全局变量window
new A();//构造函数调用: this代表新创建的对象A {}
函数原型,每一个函数都包含一个prototype属性,而且这个prototype包含唯一一个属性constructor指向构造函数对象,当将函数用做构造函数的时候,新创建的对象会从原型对象上继承属性,按照惯例,构造函数首字母要大写:
function Foo(){};//Constructor
Foo.prototype = {
constructor:Foo;//因为重写了prototype,需要显示的将constructor定义在此
userName:"Frank"};
var fooInstance = new Foo();
console.log(fooInstance.userName);//As an instance of Foo, it inherited all attributes from Foo's prototype
console.log(Foo.userName);// 函数对象Foo并没有userName属性,所以是undefined,但是Foo的原型对象有,并且被fooIntance继承
console.log(fooInstance.constructor === Foo);
注意:每个函数自身就是个对象,所以可以被赋值和像参数一样传递,但同时,它也可以被用作构造函数,用来创建其他对象。
构造函数的prototype是被所有实例共享的,例如:
<script type="text/javascript">
function Person(){};
Person.prototype =
{
constructor : Person,
name : "Frank",
friends : ["Coco","Nancy"],
sayName: function(){ alert(this.name);}
};
var p1 = new Person();
var p2 = new Person();
p1.friends.push("Van");
console.log(p1.friends);
console.log(p2.friends);
p1.sayName(); </script>
因为p1和p2共享prototype对象,所以p1的friends改变会影响到p2,这显然不是我们想要的,我们希望每个Person实例有自己单独的属性,但同时,我们又希望对一些公共方法可以共享,以节省内存。
构造方法和原型组合模式
构造方法用于定义实例属性,而原型模式用于定义方法和共享的属性。结果,每个实例都会有自己的一份实例属性的副本,同时又共享着对方法的引用,最大限度地节省了内存。有点类似于继承,但区别是prototype是单例的。
修改后的写法:
<script type="text/javascript">
function Person(name, friends){
this.name = name;
this.friends = friends;
};
Person.prototype =
{
constructor : Person,
sayName: function(){ console.log(this.name);}
};
var p1 = new Person("Frank",["coco","nancy"]);
var p2 = new Person("Daniel",["coco","nancy"]);
p1.friends.push("Van");
console.log(p1.friends);
console.log(p2.friends);
p1.sayName();
p2.sayName();
</script>
函数直接量(function literal),匿名函数 (anonymous function)
作为命名空间的函数
在函数中声明的变量在整个函数体内都是可见的,在函数的外部是不可见的(局部变量)。不在任何函数中声明的变量是全局变量,在整个JavaScript程序中都可见。
一种惯用法是用自调用匿名函数(self-invoking anonymous function) 来实现这个命名空间技术,其写法如下
(function(){
//模块代码
})();
因为默认情况下,JS是运行在全局的namespace下,而对全局变量的暴露是非常危险的,因为任何无意的修改和覆盖都会来带意想不到的错误。因此在JS开发中,尽量不要定义全局变量。在JS框架开发中此条法则体现的尤为明显,因为假如框架暴露过多的全局变量,一旦被用户修改,就可能导致框架不可用。
所以在JQuery中,整个框架通过 window.jQuery = window.$ = jQuery; 只向外部暴露了2个全局变量,即著名的$和JQuery
详细请见jQuery源码分析: http://nuysoft.iteye.com/blog/1177451
对象
JavaScript 中,除了数字、true、false、null和undefined之外,其他值都是对象,每个对象拥有三个相关的对象属性(object attribute)
- 对象的原型(prototype)指向另一个对象,本对象的属性继承自它的原型对象。对象继承是通过原型链实现的
- 对象的类(class)是一个标识对象类型的字符串
- 对象的扩展标记(extensible flag)指明了是否可以向该对象添加新属性
对象继承
var o = {};// o 从 Object.prototype 继承对象属性
o.x =1; // 定义新属性x
var p = inherit(o);//p继承o和Object.prototype
p.y = 2;
var q = inherit(p);//q继承p、o和Object.prototype
q.z =3 ;
console.log(q.x + q.y);
console.log(q.toString() + q.a);//toString继承自Object.prototype, q.a is undefined
function inherit(parent){
f = function (){};//定义一个空构造函数
f.prototype = parent; //将其原型属性设置为p
return new f();//使用f()创建p的继承对象
};
上面代码对象在内存中的示意图:
对象工厂
工厂方法这个设计模式在JS中也是经常用到,下面以jQuery源码为例,看一下对象工厂的运用。
<script language="javascript">
console.log("Start"); (function(window){//自调用函数
var //定义本地变量
core_version = "1.0.0", jQuery = function(){//这是一个工厂方法,专门用来产生jQuery对象
return new jQuery.fn.init();//下面的prototype赋值使得init函数和jQuery函数据有相同的prototype,即jQuery对象
}; jQuery.fn = jQuery.prototype = {
jquery: core_version,
constructor: jQuery,
init: function(){
return this;
},
debug: function(){console.log("debugging")}
}; // Give the init function the jQuery prototype for later instantiation
jQuery.fn.init.prototype = jQuery.fn; window.jQuery = window.$ = jQuery;//将本地变量jQuery设置为全局变量
}(window));//传入全局变量window $().debug();//$()将返回一个通过工厂方法产生的对象。
console.log("Current version is "+$().jquery);
</script>
版权声明:本文为博主原创文章,未经博主允许不得转载。
Javascript函数、构造函数、原型、类和对象的更多相关文章
- c++中在一个类中定义另一个只有带参数构造函数的类的对象
c++中在一个类中定义另一个只有带参数构造函数的类的对象,编译通不过 #include<iostream> using namespace std; class A { public: ...
- Effective JavaScript Item 51 在类数组对象上重用数组方法
Array.prototype对象上的标准方法被设计为也能够在其他对象上重用 - 即使不是继承自Array的对象. 因此,在JavaScript中存折一些类数组对象(Array-like Object ...
- Java面向对象(概述,构造函数,类与对象的关系,this关键字,成员、局部),匿名对象的调用,构造代码块(5)
Java面向对象(概述,构造函数,类与对象的关系,this关键字,成员.局部),匿名对象的帝爱用,构造代码块(5)
- JAVA基础语法:函数(方法)、类和对象(转载)
4.JAVA基础语法:函数(方法).类和对象 函数 在java中函数也称为方法,是一段具备某种功能的可重用代码块. 一个函数包括这几部分: 函数头 函数头包括函数访问修饰符,函数返回值类型, 函数名, ...
- 深度剖析前端JavaScript中的原型(JS的对象原型)
这张图片有点劝退了,哈哈哈~ 通过原型机制,JavaScript 中的对象从其他对象继承功能特性:这种继承机制与经典的面向对象编程语言的继承机制不同.本文将探讨这些差别,解释原型链如 ...
- 如何在JavaScript中手动创建类数组对象
前言 关于什么是js的类数组对象这里不再赘述.可以参考这个链接,还有这里. js中类数组对象很多,概念简单的讲就是看上去像数组,又不是数组,可以使用数字下标方式访问又没有数组方法. 例: argume ...
- 常用Javascript函数与原型功能收藏
// 重复字符串 String.prototype.repeat = function(n) { return new Array(n+1).join(this); } // 替换全部 String. ...
- JavaScript篇 深入理解JavaScript函数
JavaScript中的函数 1. 函数的定义 两种定义形式: 通过函数定义表达式来定义 通过函数声明语句来定义 函数声明语句定义一个函数 //计算阶乘的递归函数 function factorial ...
- javascript 函数详解2 -- arguments
今天我们接着上篇文章来继续javascript函数这个主题.今天要讲的是函数对像中一个很重要的属性--arguments. 相关阅读: javascript 函数详解1 -- 概述 javascrip ...
- C++类与对象(05)
类是具有惟一标识符的实体:在类中声明的任何成员不能使用extern.auto和register关键字进行修饰:类中声明的变量属于该类,在某些情况下,变量也可以被该类的不同实例所共享. 访问权限用于控制 ...
随机推荐
- 虚拟机VMBox的空间扩展和对加载进来资源的扩展
来源于:http://www.linuxidc.com/Linux/2015-01/111186.htm 其中有点bug就自己重新复制黏贴下 VirtualBox虚拟机在使用的过程中,有时会遇到磁盘大 ...
- [vijos P1880]ファーラの力
据说这是一道 JOI 的题?反正我觉着挺好的喵~ 题目看起来十分可怕,但是代码还是很短的 显而易见的,ans 因分为3个部分:1.中途增加光压的时间 2.中途减少光压的时间 3. 所有路程的总时间 发 ...
- 知识积累:CGI,FastCGI,PHP-CGI与PHP-FPM
CGICGI全称是“公共网关接口”(Common Gateway Interface),HTTP服务器与你的或其它机器上的程序进行“交谈”的一种工具,其程序须运行在网络服务器上.CGI可以用任何一种语 ...
- excel表格中关于 撤销工作表保护密码
利用宏处理,代码如下: Sub PasswordBreaker() Dim i As Integer, j As Integer, k As Integer Dim l As Integer, m A ...
- nginx location各种修饰符的匹配优先级
这作为一个备份,方便查询,毕竟nginx的强大,必然有其复杂性! Location modifier Nginx allows you to define location blocks by spe ...
- ajax 开始的loading加载
注意是异步加载方式 $.ajax({ beforeSend:function(){ $("#showMes").html('loading...'); }, success: f ...
- 关闭BrowserLink-解决异常/arterySignalR/ping未找到
在使用VS2013 MVC5开发时经常在浏览器的调试窗口看到错误信息,并且每隔两分钟就会出现错误提示:"/365e6ccac83b4cceadee2752a93b81ae/arterySig ...
- Windows下单机安装Spark开发环境
机器:windows 10 64位. 因Spark支持java.python等语言,所以尝试安装了两种语言环境下的spark开发环境. 1.Java下Spark开发环境搭建 1.1.jdk安装 安装o ...
- Nodejs日志管理包
Nodejs日志管理工具包:log4js 和 winston 1.log4js的使用 1)package.json中加入依赖 "log4js":"~0.6.21" ...
- tinyxml学习4
tinyXML一款很优秀的操作C++类库,文件不大,但方法很丰富,和apache的Dom4j可以披靡啊!习惯了使用java类库的我看到这么丰富的c++类库,很高兴!它使用很简单,只需要拷贝几个文件到你 ...