接触Web开发也已经有一段时间了,对javascript的认识也比以前有了更加深入的认识了,所以觉得应该整理一下。

一、JavaScript不支持函数(方法)的重载,用一个例子证明如下: 
function add(number) 

    alert('hello'); 
}

function add(number1, number2) 

    alert('world'); 

此时调用add(1),会弹出'world',而不是'hello',由此现象说明写在文档后面的方法会覆盖掉前面的方法,所以有一个我认为暂时是正确的原则,就是如果方法名相同,则以后面对方法为主。

二、JavaScript中函数(方法)就是一个对象,这里就不解释了,看一个例子比较直观 
function add(number) 

    alert('hello'); 

是等价于下面这种写法的 
var add = new Function("number","alert('hello')"); 
以此类推 
function add(number1, number2) 

    alert('world'); 

等价于 
var add = new Function("number1","number2","alert('world')"); 
这里一和二都是一样的,只是写法不同,底层是一样的,所以可以把JavaScript的不支持重载的现象按照面向对象的概念来理解:首先add对象指向第一个Function对象,而后引用的对象改变了,指向了第二个新的Function对象了。示意图如下

所以可以得出一个这样的结论:JavaScript中的每个函数function都是new出来的Function对象。 
   
三、如果在调用某个JavaScript函数的时候,没有给函数中的参数传值,则参数为undefined,例子如下: 
function add(number) 

    alert(number); 
    alert(number + 30); 

当在触发处调用add()的时候,显然没有传入参数值,此时先弹出undefined(未定义), 
然后弹出NaN(不是一个数Not A Number)

四、arguments是每个函数的内置对象,应用这个内置对象可以模拟面向对象的重载功能,例如 
function sum() 

    if(1 == arguments.length) 
    { 
        alert(arguments[0]); 
    } 
    else if(2 == arguments.length) 
    { 
        alert(arguments[0] + arguments[1]); 
    } 
    else if(3 == arguments.length) 
    { 
        alert(arguments[0] + arguments[1] + arguments[2]); 
    } 

调用如下: 
sum(1);    =>    1 
sum(1, 2);    =>    3 
sum(1, 2, 3);    =>    6

五、由上面的例子又可以得到,JavaScript的函数就是Function的对象,函数都有一个length属性,表示函数接收参数的个数。证明如下: 
function add() {.....} 
function minus(num) {....} 
function multiply(num1, num2) {.....} 
调用如下: 
alert(add.length)    =>    0 
alert(minus.length)    =>    1 
alert(multiply.length)    =>    2

六、JavaScript中有五种原始值,可以理解为原生数据类型(这里仅仅是值JavaScript的,不同于3GL语言),它们分别是:Undifined,Null,Boolean,Number,String 
(1)Undefined数据类型的值只有一个:undefined,这里要注意一点就是,对于JavaScript中的变量,如果只声明,而没有赋值,则该变量的值为undefined。 
例如:var s;    alert(s);   此时弹出的是undefined

(2)Null数据类型的值只有一个:null

(3)Boolean数据类型的值有两个:true和false

(4)任何整数或者浮点数都是Number数据类型中的值,另外typeof(..)函数会返回参数的类型名称,例如: 
var s;   alert(typeof(s));     弹出undefined 
var a = 1;    alert(typeof(a));    弹出number 
var b = 'hello';    alert(typeof(b));    弹出string     双引号表示原始类型在栈里 
而var c = new String("hello");    alert(typeof(c));    弹出object,是在堆中的对象了

(5)一个函数如果不返回值,则返回'undefined',typeof(..)返回的值是字符串类型的,证明如下: 
function aa() {..//里面没有return出值..}         alert(aa()); 会弹出undefined

function bb() {....;   return;  }      alert(bb);会弹出bb函数体{}中的所有源代码内容

(6)使用没有声明,并且没有赋值的变量会报错,例如, 
var s;    alert(s2);  因为s2没有声明也没有赋值,所以会报错 
alert(typeof(s));  弹出undefined 
alert(typeof(s2));  尽管s2没有声明也没有赋值,但会弹出undefined

由此可以归纳出,typeof(..)的返回值有五个:undefined,boolean,number,string,object;

(7)null与undefined的关系:undefined实际上是从null派生而来的,证明如下, 
alert(undefined == null);    会弹出true

(8)在函数体内加不加var的区别:如果在函数体的内部,变量不加var,则默认该变量为全局变量,证明如下: 
function test() 

    var s = 'hello'; 

test(); 
alert(typeof(s));此时会返回undefined 
然而 
function test() 

    s = 'hello'; 

test(); 
alert(typeof(s));会弹出string 
alert(s);会弹出hello 
由此可知,对于函数定义中的变量来说,加var表示局部变量,不加var表示全局变量

(9)强制类型转换有三种:Boolean(value),Number(value),String(value) [这里可以看作函数] 
例如, 
var s = Boolean(null);    alert(s); 会弹出false 
var s = Boolean("");     alert(s);会弹出false 
var s = Boolean("a");   alert(s);会弹出true 
new Boolean(),new String("..."),new Number("...")都是object类型的

(10)在JavaScript中,Object是所有类的父类,类似于高级语言java 
var s = new Object(); 
alert(s);    弹出[object Object] 
alert(typeof(s)); 弹出object 
alert(s.propertyIsEnumerable("prototype"));弹出false,这里是判断s中的属性是否可以枚举出来

遍历window对象中的所有属性 
for(var temp in window) 

    alert(temp); 
}

delete操作和JavaScript中的晚绑定: 
var o = new Object(); 
o.name = "scott"; 
alert(o.name);   //会弹出scott 
delete(o.name); //删除晚绑定的name属性 
alert(o.name); //会弹出undefined

七、JavaScript的面向对象的特性: 
(1)JavaScript是基于ECMAScript的,构造对象时可以直接用名字,例如 
var object = new Object;       <=>        var object = new Object(); 
var s = new String;            <=>         var s = new String(); 
var date = new Date;         <=>        var date = new Date(); 
尽管如此,还是建议加上括号,增加可读性!!!!

(2)JavaScript中的数组,长度可以动态的增加,类似于java中的ArrayList,例如 
var array = new Array();        <=>      var array = [ ]; 
array.push(1); 
array.push(2); 
array.push(3); 
alert(array.length); //弹出3 
这里也可以用var array = [1,2,3];    alert(array.length); //弹出3

(3)数组对象有一个方法sort(),可以对数组进行升序排序,例如 
var array = [3,2,1]; 
array.sort(); 
alert(array); //弹出[1,2,3] 
咋一看,很爽,但是 
var array = [1,3,21]; 
array.sort(); 
alert(array); //弹出[1,21,3] 
原因就在于:sort()方法对数组进行排序的时候,首先将数组中的每一个元素都转化为字符串,即调用每个元素的toString()方法,然后用字符串的ASCII码进行比较! 所以'21' < '3'很正常! 
另外,sort()可以接受一个排序的函数作为参数,根据参数排序,类似于java中的compare()方法 
例如, 
function compare(num1, num2) 

    var temp1 = parseInt(num1); 
    var temp2 = parseInt(num2); 
    return temp1 - temp2; 

var array = [3,1,21]; 
array.sort(compare); 
alert(array);  //弹出[1,3,21] 
这里还可以用匿名函数的方法,类似于java中的匿名类 
array.sort(function(num1, num2) { 
    var temp1 = parseInt(num1); 
    var temp2 = parseInt(num2); 
    return temp1 - temp2; 
});

(4)对象的属性方式:[1]早绑定 [2]玩绑定
所谓早绑定,就是在对象生成之前绑定好的属性,例如,
var object = new Object();
object.name = "scott";
alert(object.name);

所谓晚绑定,就是对生成好的对象增加或减少它的属性,例如,
object.hello = function() { alert('welcome'); }
object.hello();  //此时会调用object的hello方法,弹出welcome
delete object.hello();  //删除方法
object.sayName = function() { alert(this.name); }  //这里this指的是object对象,类似于java一样
object.sayName();  //此时会弹出scott
object.sayName = function(name) {   //绑定一个传参数的方法
    this.name = name;
    alert(this.name);
}
object.sayHello('tiger');   //此时弹出tiger

=================================================================

一、用工厂方式定义对象(类),这里是参照java的设计模式的工厂模式写的,例子如下

function createObject()
{
    var object = new Object();  //这里请加上var,因为是方法体内部的局部变量
    object.username = "scott";
    object.password = "tiger";

object.get = function()
    {
        alert("username: " + this.username + "/npassword: " + password);
    }
    return object;
}
调用如下,
var o = createObject();
o.get();  //此时会弹出username: scott
          //         password: tiger
该方法的好处是凡是学要对象了,不需要自己new一个出来,直接可以通过createObject生成对象,具体的细节都被封装起来了~

上面的工厂方式固然有优点,但是生成的对象属性都被默认写死成scott和tiger了,所以可以改良成如下带参数的工厂方法,例子如下,
function createObject(username, password)
{
    var object = new Object();
    object.username = username;
    object.password = password;

object.get = function()
    {
        alert("username: " + this.username + "/npassword: " + password);
    }
    return object;
}
调用如下,
var o = createObject("scott","tiger");
o.get();
该方法的好处比起一楼的方式,就是更灵活的控制了要生成的对象。

然而对于以上两种工厂方式,方法get()定义在createObject()函数的内部,从性能上考虑,没创建一个对象,就要生成一个get的function对象,但是在高级语言java中所有的对象都共同的用同一个方法,需要注意到是在JavaScript中get方法不是如此,工厂每次生成对象的时候,都会为get再生成一次相同的对象,比较消耗内存,因此,可以将get方法的定义放在createObject之外。例如,

function get()
{
    alert("username: " + this.username + "/npassword: " + this.password);
}

function createObject()
{
    var object = new Object();
    object.username = "scott";
    object.password = "tiger";
    object.get = get;
    return object;
}
调用方法一样的,有点就是优化了性能,功能还是一样~

二、构造函数的方式
function Person()
{
    this.username = "scott";
    this.password = "tiger";
    this.get = function()
    {
        alert("username: " + this.username + "/npassword: " + this.password);
    }
}
用这种方法定义比较直观,与Java中生成对象很类似了,调用如下,
var person = new Person();
person.get();

注解:当调用new Person()的时候,执行流程跳到了函数中去了,在执行第一行代码之前,会生成一个对象,而this则会指向该对象,虽然没有return该对象,但是此构造函数隐式地将对象return出去了;

另外,传递参数也是类似的,内部函数的定义也可以改良从而降低对内存的消耗,将它拿到构造函数外面单独定义,所以可以改写成如下,
function get()
{
    alert("username: " + this.username + "/npassword: " + this.password);
}

function Person(username, password)
{
    this.username = username;
    this.password = password;
    this.get = get;
}

以上这种方式还是不够直观,有另一种解决方案如下,

原型方式创建类:prototype 
function Person(){ } 
Person.prototype.username = "scott"; 
Person.prototype.password = "tiger"; 
Person.prototype.get = function() 
{ alert("username: " + this.username + "/npassword: " + this.password); } 
调用方法: 
var p = new Person(); 
p.get();

但是这里使用prototype方法生成对象,不能创建的时候初始化值,必须等对象创建出来以后,对属性修改。 
var person1 = new Person(); 
var person2 = new Person(); 
person1.username = 'hello'; 
person1.get();   //hello tiger 
person2.get();   //scott tiger

JavaScript中的字符串也是不可变的,与java机制中一样,属于final类型的,字符串的拼接一会生成新对象

如果Person.prototype.username = new Array(); //如下面一楼贴出的图片person1和person2会共享scott
    person1.username.push("scott");
    person1.get(); //scott
    person2.get(); //scott

混合的构造函数与原型方式,属性采用构造函数的方式定义,方法采用原型方式定义(这里比较推荐这种方式)
可以避免上面的共享属性的弊端,例如,
function Person(username,password)
{
    this.username = username;  //这里如果this.username = new Array(); 则新对象不会共享username
    this.password = password;
}
Person.prototype.get = function()
{
    alert("username: " + this.username + "/npassword: " + this.password);
}
调用方法:
var p = new Person("scott","tiger");
p.get();

另外还有一种方式:动态的原型方式
function Person()
{
    this.username = "scott";
    this.password = "tiger";
    if(typeof Person.flag == "undefined")  //或者Person.flag == undefined
    {
        Person.prototype.get = function()
        {
            alert("username: " + this.username + "/npassword: " + this.password);
        }
        Person.flag = true;
    }
}

下面来看看用JavaScript模拟java的继承特性
(1)继承的第一种方式:对象冒充
function Parent(username)
{
    this.username = username;
    this.hello = function()
    { alert("username: " + this.username); }
}

function Child(username,password)
{
    this.method = Parent;
    this.method(username);
    delete this.method;
    this.password = password;
    this.world = function()
    { alert("password: " + this.password); }
}

根据上图,和带下划线的代码段,method属性作为桥梁引用Parent对象,调用Parent的构造函数后,删除了该属性!!
注意如果吧带下划线的代码段替换为Parent(username);是不行的,因为这样的话Parent中的hello()方法不能继承下来~

调用上面的继承
var parent = new Parent('father');
var child = new Child('son','scott');

parent.hello(); //father
child.hello();  //son
child.world();  //scott

由此可见继承机制确实实现了!!!!

(2)继承的第二种方式:call()方法
这里先介绍call()方法:每个function,即Function对象都有call()这个方法,call(param1,param2,...),
param1表示调用call()方法的函数内部的this,param2,...对应调用call()方法的函数中的参数列表,例如,

function test(str)
{
    alert(this.name + " " + str);
}
var obj = new Object();
obj.name = 'scott';
test.call(obj,'tiger'); //这里将obj对象赋给test中的this,弹出scott tiger

了解了call()的功能以后,我们来用call()实现继承机制,例子如下:

function Parent(username)
{
    this.username = username;
    this.hello = function()
    {
        alert(this.username);
    }
}

function Child(username, password)
{
    Parent.call(this,username);
    this.password = password;
    this.world = function()
    { alert(this.password); }
}

调用方法类似,这里就省略了。。。

(3)继承的第三种方式:apply()方式
这里对比一下apply()和call()
call(parm1,parm2,...,parmN)  多个参数

apply(parm1,new Array())  <=> apply(parm1,[parm2,...,parmN])  两个参数

归纳一下,apply方法的第一个参数和call一样,第二个参数是call后面参数组成的一个数组

下面用apply()来实现继承的机制,如下:
function Parent(username)
{
    this.username = username;
    this.hello = function()
    { alert(this.username); }
}

function Child(username,password)
{
    Parent.apply(this,new Array(username));  //等价于Parent.apply(this,[username]);
    this.password = password;
    this.world = function()
    { alert(this.password); }
}

(4)继承的第四种方式:原型链方式
function Parent() { }
Parent.prototype.hello = "hello";
Parent.prototype.sayHello = function()
{ alert(this.hello); }

function Child() { }
Child.prototype = new Parent();
Child.prototype = "world";
child.prototype.sayWorld = function()
{
    alert(this.world);
}

调用一下:
var child = new Child();
child.sayHello();  //hello
child.sayWorld();  //world

(5)继承的第五种方式:混合方式(最佳实践,推荐使用)

function Parent(hello)
{
    this.hello = hello;
}

Parent.prototype.sayHello = function()
{ alert(this.hello); }

function Child(hello,world)
{
    Parent.call(this,hello);
    this.world = world;
}

Child.prototype = new Parent();
Child.prototype.sayWorld = function()
{ alert(this.world); }

调用一下:
var child = new Child('hello','world');
child.sayHello();  //hello
child.sayWorld();  //world

最后举个例子来应用JavaScript的继承机制的应用

function Shape(edge) //一个抽象的形状
{
    this.edge = edge;
}

Shape.prototype.getArea = function() //获取形状的面积,类似于接口中的方法,这里先返回-1
{ return -1; }

Shape.prototype.getEdge = function() //返回形状的边有多少条
{ return this.edge; }

下面定义子类,三角形
function Triangle(bottom,height) //三角形,出入参数为底边和高
{
    Shape.call(this,3);
    this.bottom = bottom;
    this.height = height;
}
Triangle.prototype = new Shape();
Triangle.prototype.getArea = function() //返回三角形的面积,覆盖父类的方法
{ return 0.5 * this.bottom * this.height; }

调用三角形的对象和方法:
var triangle = new Triangle(10,4);
alert(triangle.getEdge()); //3
alert(triangle.getArea()); //20

下面再定义一个四边形
function Rectangle(bottom, height)
{
    Shape.call(this,4);
    this.bottom = bottom;
    this.height = height;
}
Rectangle.prototype = new Shape();
Rectangle.prototype.getArea = function()
{ return this.bottom * this.height; }

调用四边形的对象和方法
var rectangle = new Rectangle(10,20);
alert(rectangle.getEdge());  //4
alert(rectangle.getArea());  //200

JavaScript语言知识收藏的更多相关文章

  1. Javascript语言精粹之正则表达式知识整理

    Javascript语言精粹之正则表达式知识整理 1.正则表达式思维导图 2.正则表达式常用示例 2.1 移除所有标签,只留下innerText var html = "<p>& ...

  2. javascript语言精粹mindmap

    javascript语言精粹mindmap 最近刚刚读完<javascript语言精粹>,感觉其中的内容确实给用js作开发语言的童鞋们提了个醒——js里面坑很多啊 不过,我也并不完全认同书 ...

  3. AST抽象语法树——最基础的javascript重点知识,99%的人根本不了解

    AST抽象语法树——最基础的javascript重点知识,99%的人根本不了解 javascriptvue-clicommonjswebpackast  阅读约 27 分钟 抽象语法树(AST),是一 ...

  4. 第一章:Javascript语言核心

    本节是javascript语言的一个快速预览,也是本书的第一部分快速预览. 读此书之前,感谢淘宝技术团队对此javascript核心的翻译,感谢弗拉纳根写出此书.感谢你们无私的分享,仅以此笔记献给你们 ...

  5. 试读《JavaScript语言精髓与编程实践》

    有幸看到iteye的活动,有幸读到<JavaScript语言精髓与编程实践_第2版>的试读版本,希望更有幸能完整的读到此书. 说来读这本书的冲动,来得很诡异,写一篇读后感,赢一本书,其实奖 ...

  6. 【转】R语言知识体系概览

    摘要:R语言的知识体系并非语法这么简单,如果都不了R的全貌,何谈学好R语言呢.本文将展示介绍R语言的知识体系结构,并告诉读者如何才能高效地学习R语言. 最近遇到很多的程序员都想转行到数据分析,于是就开 ...

  7. JavaScript语言精粹 笔记01 语法 对象

    内容比较简单,只是从头梳理一下JS的知识 语法空白标识符数字字符串语句 对象对象字面量检索更新引用原型反射枚举删除减少全局变量污染  语法 1 空白 空白可能表现为格式化字符或注释的形式.空白通常没有 ...

  8. JavaScript 语言的历史

    说明:此类博客来自以下链接,对原内容做了标注重点知识,此处仅供自己学习参考! 来源:https://wangdoc.com/javascript/basic/introduction.html 1.诞 ...

  9. 林大妈的JavaScript基础知识(三):JavaScript编程(4)数组

    数组,是一段线性分配的,具有非常高性能的数据结构.简单地说,数组以连续的空间存储,通过整数地计算偏移量访问其中的元素,将读取修改的时间复杂度降低至O(1),我们称之为猝发式存取.是不是非常期待?没错, ...

随机推荐

  1. 【LeetCode】338. Counting Bits (2 solutions)

    Counting Bits Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num  ...

  2. leveldb - menifest文件格式

    MANIFEST文件是Level DB的元信息文件,它里面的格式是leveldb的Log格式,一个menifest是一个record: void VersionEdit::EncodeTo(std:: ...

  3. Java历史版本下载

    下载个以前版本的Java工具不容易.Java SE 6 版本拿去: http://www.oracle.com/technetwork/java/javasebusiness/downloads/ja ...

  4. 数据仓库专题(23):总线矩阵的另类应用-Drill Down into a More Detailed Bus Matrix

    一.前言 Many of you are already familiar with the data warehouse bus architecture and matrix given thei ...

  5. Intellij idea 乱码问题(英文操作系统)

    英文操作系统导致 Debug 下的变量查看时显示乱码,可通过改变字体解决此问题.

  6. 移动应用安全开发指南(Android)--完结篇(http://www.bubuko.com/infodetail-577312.html)

    1.认证和授权 概述 认证是用来证明用户身份合法性的过程,授权是用来证明用户可以合法地做哪些事的过程,这两个过程一般是在服务器端执行的,但也有的APP出于性能提升或用户体验等原因,将其做在客户端完成, ...

  7. jdbc无法连接数据解析

    1.网络原因 2.账户权限问题 账户是否赋予以下的权限: grant connect, resource to ADM_BI; grant read, write on directory BACKU ...

  8. win7搭建ios开发环境

    安装过程参考文章: http://jingyan.baidu.com/article/ff411625b9011212e48237b4.html http://www.loukit.com/threa ...

  9. 网站CSS选择器性能讨论

    CSS选择符由一些初始化参数组成,这些参数指明了要应用这个CSS规则的页面元素.作为一个网站的前端开发工程师,应该避免编写一些常见的开销很大的CSS选择符模式,尽量编写高效的CSS选择符,从而加快页面 ...

  10. dell新服务器安装系统

    公司新采购的dell 630服务器,但是第一次安装操作系统的时候比较麻烦,每次都要重新琢磨下. 现在记录一下,以供下次参考 1.插入服务器自带光盘,设置CD启动,选择部署OS 2.配置raid,然后插 ...