你应该知道的几个js知识

1.在javascript的块级作用域是以函数来决定的.

     if(true){
         var scopeName = "felayman";
     }
    print(scopeName);

上述虽然scopeName是在{}内声明的,但是它不属于块级作用域,在{}范围内依然能进行访问.因此,如果想在javascript中声明一个块级作用域,需要借助于函数来实现,如

 <span style="font-size:18px;"> function scope(){
        if(true){
            var scopeName = "felayman";
        }
    }</span>

这样,scopeName才属于一个函数级(块级)作用域,在函数外是无法访问scopeName的.

2.javascript中的变量查找链,如

 <span style="font-size:18px;">   var scope = "golbalScope";
    var fun = function(){
       alert(scopr);
        var scope = "funcScope";
    };
    fun();</span>

其结果为undefined,上述的代码可能跟我们所想的有所不同,没有输出golbalScope,也没有输出funcScope,而是输出了undefined?这是声明原因呢?这个是javascript的一个重要特性---作用域搜索顺序,当我们去访问某个变量的时候,它会优先搜索scope所在环境,因此搜索到了var
scope = "funcScope";,因此会

抛弃掉上一级环境的var scope = "golbalScope";也就是var scope = "golbalScope";会被变量scope所在的环境给屏蔽掉,然后当程序执行到alert(scope);的时候,但是

scope在当前环境中并没有进行初始化,因而输出了undefined.

3.javascript的函数作用域的嵌套

<span style="font-size:18px;"> var fun = function(){
    var scope = "scope_one";
    (function(){
        alert(scope);
        var scope = "scope_two";
        (function(){
            alert(scope);
        })();
    })();
};
fun();</span>

这个例子的结果为,undefined和scope_two,正如上面一个例子一样,我们可以理解其结果行为,但是我们必须去注意,函数作用域的嵌套关系是在定义的时候决定的,而不是调用的时候决定的,也就是说,javascript的作用域是静态作用域,也叫词法作用域,这个例子主要是想说明闭包,在javscript中,一般情况下闭包就是匿名函数,而关于闭包的定义,有这么一种说法:由函数及其封闭的自由变量组成的集合体.,因此在一般情况下,在javascript我们视函数即为闭包,我们看一个例子

<span style="font-size:18px;">function print(s){document.write(s+"<br/>")};
  var getResult = function(){
    var count = 0;
    var get = function(){
        count++;
        return count;
    };
    return get;
};
var counter = getResult();
print(counter());
print(counter());
print(counter());</span>

结果为1,2,3.如果熟悉其他语言,或许会恨困惑这个结果,因为函数,俗称方法,在其他语言中就是一个保存临时变量和结果的一个容器,当函数执行完毕后,会释放该函数内的所有的局部变量和临时结果,因此当我们每次调用同一个函数的时候,其结果是不变的,但是在jabascript,却因为闭包改变了这个规则.这个也是闭包的特性---当一个函数返回它内部定义的一个函数的时候,就产生了一个闭包,闭包不但包括被返回的函数,还包括这个函数的定义环境,上面的例子,当函数getResult()的内部函数get被一个外部变量counter引用的时候,counter和getResult()的局部变量就形成一个闭包.因此上述的counter()其实就是get(),打印counter()的值,就是打印get()的值,但是于此同时get()函数属于getResult()函数内部的一个闭包(或者可以理解一个布局变量,或者理解get()在getResult()函数的作用域内),在该闭包内依然引用着它的上一级作用域,即getResult()函数作用域,具体的说,在get()函数内部使用了getResult()函数内的变量,因此,虽然我们在getResult()函数外部调用了一个看似与getResult()函数关系不大的counter()函数,但是却是在getResult()函数内部环境去执行的counter()函数.也就是说print(counter());

print(counter());print(counter());)这段代码看似是在getResult()外部执行,其实本质上是在getResult()函数内部执行的,因此上述代码完全等效于下述代码:

<span style="font-size:18px;">/**
 * Created by felayman on 2014/5/27.
 */
  function print(s){document.write(s+"<br/>")};
  var getResult = function(){
    var count = 0;
    var get = function(){
        count++;
        return count;
    };
    print(get());
    print(get());
    print(get());
};
getResult()</span>;

但是如果我们在使用的时候这样使用的话,就没有闭包的优势了----与外界失去了联系,也就是与其他语言中的函数(方法)一样的,而javascript中的函数,也正是由于闭包的特性,才被称为最实用于函数式编程的语言.

4.this所指向的内容

 function print(s){document.write(s+"<br/>")}
    var func1 = {
        name:"func1scope",
        func:function(){
            print(this.name);
        }
    };
    var func2 = {
        name:"func2scope"
    };
    func1.func();  //输出func1
    func2.func = func1.func;
    func2.func();  //输出func2
    var name = "windowscopr";
    window.func = func1.func;
    func();

上述代码会输出:func1scope   func2scope    windowscopr,因此,可以看出this的指向是随着其环境而发生变化,但是我们只需要记着一句话即可---this始终指向其执行期间的环境对象,而非定义时的环境对象.

5.call和apply

如果说在javascript中最让人困惑和难以理解的,

其中call和apply的功能是以不同的对象作为上下文来调用某个对象的函数,或者--就是允许在一个对象中去调用另一个对象中的同名函数(没有会被复制)并执行(摘自--NodeJS开发指南).如下面的例子:

<span style="font-size:18px;">var oneUser = {
    name:"oneUser",
    getName:function(){
        alert(this.name);
    }
};
var otherUser = {
    name:"otherUser",
};
oneUser.getName.call(otherUser);</span>

可以这样理解,我们以每一个对象内部都有一个call对象(函数就是对象),该对象没有具体指向,但是允许指向任何一个对象内部的另一个对象.而applay与call的用法没有上面区别,只是接受的参数不同而已.

6.原型

如果要给原型一个定义,百度百科上说的很详细,但是很抽象,很难理解,而在NodeJs开发指南中,作者用了一个很好的例子----原型就好像是一件艺术品的原件,我们通过一台100%精确的机器把这个原件复制出很多件,如果我们了解类似java的面向对象语言的话,就会知道,在java中所有的对象都来自于类,而C++中所有的对象来自于构造器,但是javascript是一种基于面向对象语言,它既有类似C++的构造器,也有类似类的原型.其实我更倾向于一篇博文中的理解,在javascript中

,原型就是java中的一个类的一个对象,该对象存储该类的所有静态属性或方法.我更建议使用这种方法来理解原型.因为的确是这样的,javascript中使用原型的目的就是让某一类型的所有对象共享一些属性和函数,提供代码的复用性,同时也隐藏一些属性和函数的细节,即提高其内聚性和封装性,这也是javascript基于面向对象的特性.

<span style="font-size:18px;">function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.getInfo = function(){
        return "name ="+this.name+",age = "+ this.age+",job = " +this.job;
    }
}
</span>

上述代码没有使用,原型,因此我们在使用new关键字来创建对象的时候,可以根据不同的name,age,job来构件许许多多的Person的对象,这些对象的属性都不相同,但是作为常识,我们都知道Person都有一个共同的行为--说话(不去钻牛角尖),当然我们可以改写上面的代码来满足我们的需求:

<span style="font-size:18px;">function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.getInfo = function(){
        return "name ="+this.name+",age = "+ this.age+",job = " +this.job;
    }
    this.say = function(){
        alert("人都会说话");
    }
}
</span>

这样的代码是允许的,但是不是被建议的,因为我们在创建一个Person对象的时候,就会在内存中生成say()函数的内容空间,或许在少量的这样的行为的时候我们允许这么做,但是我们再思考一下,如果一个函数中有大量的行为或者属性都像say()函数一样是每一个Person对象所共同拥有的,必然Person会说话,会跑,会思考,会苦,会笑.........如果有了大量类似的属性或行为的话,我们还是写在函数内部的话,就不好了,因为我们在创建基量很大的对象数量的时候,我们就额外增加了非必须且可避免的内存开销了,因为每个对象在内存中都会开辟其所拥有的方法空间,这是不建议的,因此,我们使用了原型的话,这个问题就可以避免了,我们只需要在内存的其他地方创建一个原型对象,改对象保存着Person所有的共同属性或者方法,只要在每个Person实例对象中保存一个指向改内存空间的引用或句柄即可.这样当我们即使创建再多Person实例对象,也没有多少内存开销,这个理解就是javascript原型的特性之一.因此上述代码改写成下面就好了:

<span style="font-size:18px;">function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
}
Person.prototype.getInfo = function(){
    return "name = "+this.name+",age = "+this.age+",job ="+this.job;
};
Person.prototype.say  =function(){
    console.log("人都会说话");
};</span>

你应该知道的几个js知识

时间: 2024-11-03 03:41:10

你应该知道的几个js知识的相关文章

JS知识整理之 Call&amp;Apply方法

JavaScript中的函数也是对象,和其他JS对象一样也可以包含方法,其中Call和Apply就是其中比较重要的方法,可以用来间接的调用函数.这两个方法允许显式制定调用所需的this值,也就是说所有函数可以作为任何对象的方法来使用,哪怕这个函数不是那个对象的方法. Call方法: 语法:call([thisObj[,arg1[, arg2[,   [,.argN]]]]]) Apply方法: 语法:apply([thisObj[,argArray]]) Call和Apply方法作用相同,但从以

得于吾师傅的js知识 js类,单写模板,和私有保护的方法

js的类的写法: 1,写法一:function内部包含this.function()如代码: var origin_class = function(name) { var lover = ''; this.getLover = function(hername) { return this.lover = hername; } this.show = function(hername) { return this.getLover(hername)+'love'+name; } } var t

Angular JS知识小总结

1.什么是Angular JS? AngularJS 是一个为动态WEB应用设计的 JavaScript结构框架. 2.Angular JS的用处? --它是为了克服HTML在构建应用上的不足而设计; --适用于CRUD应用,是为了消除页面上的DOM操作而生.它的核心理念是借鉴了MVC框架,但是它其实更接近于MVVM.viemmodel是一个原生的javascript对象,angularJS把view和model加到viemmodel上,从而实现数据的绑定.而且这种绑定是双向的,即view变化

前端必会的js知识总结整理

1.晨曦. 2.js是一门什么样的语言及特点? js是一种基于对象和事件驱动的并具有相对安全性的客户端脚本语言.也是一种广泛用于web客户端开发的脚本语言,常用来给html网页添加动态功能,如响应用户的各种操作. 主要的目的是为了解决服务器端语言遗留的速度问题,为客户提供更流畅的浏览效果. (详细拓展:http://www.360doc.com/content/14/0317/11/10186276_361233415.shtml) 3.js的数据类型? 基本数据类型:String.boolea

web前端之每天学一点js知识第四期

<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>无标题文档</title> </head> <body> <img src="img/0.JPG" /> <img src=&

移动端js知识总结

1.如果使用jquery绑定touch事件的话,获取touchstart,touchmove的触点坐标用 e.originalEvent.targetTouches[0].pageX, 获取touchend则用 e.originalEvent.changedTouches[0].pageX 2.有些版本的iphone4中, audio和video默认播放事件不会触发 比如使用window.onload或计时器等都不能触发播放,必须用JS写事件让用户手动点击触发才会开始播放,比如 $(docume

js知识简单归纳

js简单的归纳 基本类型 number,string,boolean,null,undefined 组合类型 一种对象类型: object 数组 函数 对象 正则 关于函数 作用域 闭包 构造函数 原型链 关于对象 类 类的继承 实例方法 静态方法 私有方法 运算符 算术 逻辑 关系 位 语句 循环分支语句 JS中声明变量的几种方式 a,b参数变量 如function fn(a,b){} p,q是var定义的 m:函数声明:FD 他们的区别 他们都会变量上浮.(variable hoist);

js知识体系的梳理一

今天简单的总结了js的一些东西,梳理下整个体系,每一次的总结都会有不同的收获:js总结一一.[获取元素]: 1.通过ID: var oBtn=document.getElementById('btn1'); var oDiv=document.getElementById('div1'); 2.通过标签:var aDiv=document.getElementsByTagName('div'); 操作一组元素就要用循环: for(初始值;循环条件;自增自减条件){} 有长度的用for循环 初始值

js知识逐步总结(连载中....)

一.JS原生方法:get.ElementById();get.ElementsByTagName();alert();console.log();number();parseInt();parseFloat();isNaN(); 二.属性:innerHTML, value, type, href, src, alt, 自定义属性: 三.事件:鼠标事件.键盘事件.系统事件.表单事件.自定义事件......1.鼠标事件:onclick 鼠标点击onmouseover 鼠标移到某个东西onmouseo