怎么理解js 里面的js 语法检查

js 面向对象理解
js 面向对象理解
这个话题已经很久没有人谈了.高手懒得谈,新手不敢谈.最近计划想写一套网页游戏的UI引擎,特地开贴写篇文章,与大家分享下js的面向对象特性及其实现,与大家共勉之.
主要是面向新手,因为多年前我也是新手,非常渴望有高手一谈js的面向对象.
以下总结,是代表着自己的一种理解,我希望去培养程序员的一些直觉.而不是书本化的,很深入,很晦涩的知识.首先要理解以下这些概念:
1, js中函数可以当做一种数据类型来看,而事实上他是一种Function对象的实例.
2, 函数与对象的对等性,在JS中对象一般采用函数来定义。
3, js中的变量的作用域是词法性的.
下面先对这些进行一下说明:
1, js中函数可以当做一种数据类型
&&&&&&& 在js中变量都是可变类型的,但是并不是没有类型,看如下代码:
var&a=1;var&b="1";alert(typeof&a);&&&//numberalert(typeof&b);&&&//stringalert(a+1);&&&&&&&&//2alert(b+1);&&&&&&&&//11
通过以上代码不难看出,即使你还可以写 a="2";以改变a的类型,但是仍然应该在任何时候清楚的明白变量的类型.
这种变量类型的易变性和对象的易变性 即是js的弊端,也是它如此强大的原因.他把自由留给了你,如果可以我们可以制定自己的编写规范来约束自己而不是靠语言的实现本身.
下面说说函数的相关特性:
function&Person(){&&alert("a");}var&Person=function(){&&alert("b");}
以上两种写法等价,都是定义了名为 Person的函数,函数功能也相同,即弹出一个字符.&我们可以如下这样调用:
Person();//事实上js引擎会认为你给window增加了一个成员,以上等价于:window.Person=function(){&...}//你也可以如下调用:window.Person();
alert(typeof Person)& //function
alert(typeof window.Person)& //function&&& function即为Person的数据类型
这也意味着,当我们用window.open()打开一个窗口,或者在iframe等框架中要使这个方法,需要先获得定义这个方法的window对象.如:
&div&&iframe&&src="1.html"/&&/div&&script&type="text/javascript"&var&Person=function(){&&&alert("c");}&/script&
在1.html中.我们需要如下调用此函数:
1.html&script&type="text/javascript"&window.top.Person();&&//window.top是获得顶层的window对象&/script&
当一个函数被重复定义,后一个定义会被前一个定义给覆盖.跟变量的特性一样.
下面我们进行下一步:
var&method=function(a,b){&&&alert(a+b);}如下调用:method(1,2);//我们定义一个method方法,传入两个变量.//方法弹出两个变量的和.//再看下面这个函数var&method1=function(a,b,func){&&&&func(a+b);}//要调用下面这个方法,需要定义一个方法以传进去.方法定义如下:var&method2=fucntion(arg1,arg2){&&&alert(arg1+arg2);}//method1&如下进行调用method1(1,2,method2);&&&//注:这里用的是method2&,而不是method2();
应该不难看出 method2 这个函数作为一种变量的性质.
为了进一步说明这个问题,我们再看几个例子:
&&setInterval(method2,100);&&setInterval("function(){alert('d');}",100)
& setInterval(function(){alert("d");},100)//以上两种方法都是调用一个函数,&&只不过一个是传入的方法本身,一个是传入的字符串.//我们不知道&&setInterval&&的内部的真实实现,但是可以假想如下:function&setInterval(code,delay){&&&&var&&&&&if(typeof&code=="string")&&&&{&&&&&&&&&func=eval(code);&&&&}else&&&&{&&&&&&&&&&func=&&&&}&&&&//...}
js函数的这种特性和用法,类似于& c#里的 委托,& 特别是framework3.5里的匿名函数.& 微软在动态语言方向下了不少功夫.....
//& 为了不丢失 ,先发布一次.......& 然后继续
总之一句话:& 函数 在使用上跟一个平常的变量并没有什么本质不同.&& 这个跟其它语言vb, c, java有些差别
下面对函数再深入一步:
//对比下面两段代码function&Show1(a,b){&&&&return&a+b;&&&&&&&&&&&&&//Show1的返回值是一个两数相加的和&&&&如不申明,都认为参数为整数.}function&Show2(a,b){&&&&var&c&=&"输入的参数为:";&&&&return&function(){&&&&&&&&return&c+a+","+b+"其结果为"+(a+b);&&&&}}alert(typeof&Show2(1,2));&&//Show的返回值是一个函数alert(Show2(1,2)());&&&&&&&//弹出把上面返回值进行执行的结果:&&输往入的参数为:1,2其结果为3.
里面的那个函数在js被称为闭包函数,他是一种函数中的函数.& 如果对闭包不太理解,你就简单的把函数看成一种数据类型,跟string& ,number一样即可.这样就容易理解闭包了.
闭包容易产生一些奇怪的特性,如下:
function&Person(name){&&&&&var&_name=&&&&&return&function&Eat(food)&&&&&{&&&&&&&&&alert(_name+"吃了"+food);&&&&&}}var&p=&Person("马化腾");&&&//此时p是一个函数.p("糙米饭");&&&&&&&//马化腾吃了糙米饭p("马铃薯");&&&&&&&//马化腾吃了马铃薯//基至我们可以写出更变态的函数:function&Person(name){&&&&&var&_name=&&&&&return&function(food)&&&&&{&&&&&&&&&var&eatit=_name+"吃了"+&&&&&&&&&return&function(dosomething){&&&&&&&&&&&&&&&alert(eatit+dosomethig);&&&&&&&&&}&&&&&}}//如果调用我就不再详述了,大家可以自己写写如何调用.
对以上有疑惑的可以回贴,因为写得比较随意,代码也是直接在编辑器里写的,可以会有些许错误,请大家指正.
2, 函数与对象的对等性,在JS中对象一般采用函数来定义。
在js中对象一般采用函数来定义,因为要讲解到 js的面向对象的特性,此处我借用一种传统的面向对象的语言c# 来协助进行解释,读者没有c#基础的可以直接略过c#代码.
//js中没有class&关键字,也没有对有无返回值进行关键字的区分.&js的语法会灵活得让你无所适从而犯很多错误.function&Person(name,sex){&&&&&this.name=&&&&&&&&//实例成员&&&&&this.sex=&&&&&&&&&&&&&&&this.show=function(){&&//实例方法&&&&&alert(this.name+this.sex);&&//注意这里用到了this,而不是直接用的&&name&&和&&sex&还在跟上一点中的Person方法进行对比.&&&&&}}
//调用如下:
var p=new Person("马化腾","...");
&跟c#比较一下:
public&class&Person{&&&&public&Person(name,sex)&&&&{&&&&&&&&this.name=&&&&&&&&this.sex=&&&&}&&&&public&string&&&&&public&string&&&&&public&void&show()&&&&{&&&&&&&&Console.Write(name+);&&&&}}//调用如下:Person&p=new&Person();p.show();
//每粘一次代码,都会自动被粘到顶部,不知道大家是不是这样.&&后续稍候...
这是js的一种定义对象的最基本的形式,后面我将在后面几节,对json,对象字面量,原型式继承中说说更多的js创建对象的方法.
3, js中的变量的作用域是词法性的.
这点跟其它语言有很大不同.
变量的在作用域只在声明他的范围里有效,如上述代码中的闭包的例子.在下面再拷背一份.
function&Show2(a,b){&&&&var&c&=&"输入的参数为:";&&&&return&function(){&&&&&&&&return&c+a+","+b+"其结果为"+(a+b);&&&&}}var result=Show2(1,2);
var a=result();
当Show 方法已经执行结束后.& result仍然能够访问show的局部变量 c ,& 原因是因为返回的这个方法是在Show内部定义的. 看这个有点让人模糊不清.& 请再看下面各单纯一点的例子:
function&Person(name){&&&&&_name=&&&&function&Show()&&&&{&&&&&&&&&alert(_name);&&&&}&&&&return&S}var&p=Person("马化腾");var&p();&&&//此时这个方法仍然能够访问&&Person方法的局部变量,因为Show方法定义在Person方法的内部.他和_name有同样的词法域.
词法域:只要是在同样的地方定义,就可以互相访问,而不是在方法执行的作用域,即变量的生命周期.
了解这点后,我将在下一节,来讲解,用灵活的js怎么实现& 信息的封装,并进而得出典型的面向对象特性的实现.
发表评论:
TA的推荐TA的最新馆藏[转]&如何理解和熟练运用js中的call及apply?
有时候看一两个关于apply或call的小例子,感觉能够理解一点点但是下次碰到又要纠结半天才能转过弯来~而且不知道怎么应用到实际工作当中去~
LZ要先明白存在call和apply的原因,才能记得牢一点:
在javascript OOP中,我们经常会这样定义:
function cat(){}cat.prototype={
food:"fish",
say: function(){
alert("I love "+this.food);
}}var blackCat =blackCat.say(); 但是如果我们有一个对象whiteDog = {food:"bone"},我们不想对它重新定义say方法,那么我们可以通过call或apply用blackCat的say方法:blackCat.say.call(whiteDog);所以,可以看出call和apply是为了动态改变this而出现的,当一个object没有某个方法,但是其他的有,我们可以借助call或apply用其它对象的方法来操作。用的比较多的,通过document.getElementsByTagName选择的dom 节点是一种类似array的array。它不能应用Array下的push,pop等方法。我们可以通过:var domNodes =
Array.prototype.slice.call(document.getElementsByTagName("*"));这样domNodes就可以应用Array下的所有方法了。其他的就不提了,讲多了反而迷惑。
call 和 apply 都是为了改变某个函数运行时的 context 即上下文而存在的,换句话说,就是为了改变函数体内部 this 的指向。因为 JavaScript 的函数存在「定义时上下文」和「运行时上下文」以及「上下文是可以改变的」这样的概念。二者的作用完全一样,只是接受参数的方式不太一样。例如,有一个函数 func1 定义如下:var func1 = function(arg1, arg2) {};就可以通过 func1.call(this, arg1, arg2); 或者 func1.apply(this, [arg1, arg2]); 来调用。其中 this 是你想指定的上下文,他可以任何一个 JavaScript 对象(JavaScript 中一切皆对象),call 需要把参数按顺序传递进去,而 apply 则是把参数放在数组里。JavaScript 中,某个函数的参数数量是不固定的,因此要说适用条件的话,当你的参数是明确知道数量时,用 call,而不确定的时候,用 apply,然后把参数 push 进数组传递进去。当参数数量不确定时,函数内部也可以通过 arguments 这个数组来便利所有的参数。
函数调用的三种方式:obj.myFunc();myFunc.call(obj,arg);myFunc.apply(obj,[arg1,arg2..]);
apply: call:NOTE: While the syntax of this function is almost identical to that of call(), the fundamental difference is that call() accepts an argument list, while apply() accepts a single array of arguments. call 和 apply 的区别只在于这两个函数接受的参数形式不同。Example: 判断一个变量是不是Arrayvar a = {};var b = []Object.prototype.toString.call(a);
// 输出为: "[object Object]" Object.prototype.toString.call(a);
// 输出为: "[object Array]" update: 使用call和apply方法,可以改变对象方法的运行环境,例如,有一个类Manfunction Man() {}
Man.prototype = {
valet: false,
wakeUp: function(event) {
console.log(this.valet + "? Some breakfase, please.");
//get "undefined? Some breakfast, please
var button = document.getElementById('morning');
button.addEventListener(
wooster.wakeUp,
//使用apply来改变 wakeUp 的上下文环境,即 wakeUp 中的this
var button = document.getElementById('morning2');
button.addEventListener(
function() {
Man.prototype.wakeUp.apply(wooster, arguments);
ps:以上代码例子来自与《深入Ajax架构与最佳实践》3.1 对象与事件触发
obj.call(thisObj, arg1, arg2, ...);
obj.apply(thisObj, [arg1, arg2, ...]);
两者作用一致,都是把obj(即this)绑定到thisObj,这时候thisObj具备了obj的属性和方法。或者说thisObj『继承』了obj的属性和方法。唯一区别是apply接受的是数组参数,call接受的是连续参数。function add(j, k){
return j+k;
function sub(j, k){
return j-k;
我们在控制台运行:add(5,3); //8
add.call(sub, 5, 3); //8
add.apply(sub, [5, 3]); //8
sub(5, 3); //2
sub.call(add, 5, 3); //2
sub.apply(add, [5, 3]); //2
通过call和apply,我们可以实现对象继承。示例:var Parent = function(){
this.name = "yjc";
this.age = 22;
var child = {};
console.log(child);//Object {} ,空对象
Parent.call(child);
console.log(child); //Object {name: "yjc", age: 22}
以上实现了对象的继承。更多阅读:js笔记——call,apply,bind使用笔记 - 飞鸿影~ - 博客园
JS functions are objects JS函数是对象,没什么特别的... that have .call and .apply methods 这些对象只不过有call和apply两个特别的方法而已... both take an object as the first argument call和apply的第一个参数是任一个对象... which specifies the target where the function runs against 既函数的执行(作用)目标function fn (a) { ... }
var obj = { ... }
// 在obj上执行fn
fn.call(obj, ...)
fn.apply(obj, ....)
我也是刚刚理解,你首先要知道call和apply是Function的方法,他的第一个参数是this,第二个是Function的参数。比如你的方法里写了this,普通调用这个方法这个this可能是window。而如果你用了call,第一个参数写啥,里面的this就是啥
其实就是动态的改变this了,下面例子就说明了。。。
function add(a, b){console.dir(this);}
function sub(a, b){console.dir(this);}
add.call(sub, 1, 2);
"sub(a, b)"
sub.apply(add, [1, 2]);
"add(a, b)"
call和apply可以用来重新定义函数的执行环境,也就是this的指向。通过一个操作DOM的例子来理解。function changeStyle(attr, value){
this.style[attr] =
var box = document.getElementById('box');
window.changeStyle.call(box, "height", "200px");
call中的第一个参数用于指定将要调用此函数的对象,在这里,changeStyle函数将被box对象调用,this指向了box对象,如果不用call的话,程序报错,因为window对象中没有style属性。apply的用法:window.changeStyle.apply(box, ['height', '200px']);
=========更新:日========如果call或apply的第一参数是null的话, this指向window
你首先要明白 this 是个参数,然后就好理解了:普通的函数调用隐式传入 this,call 和 apply 可以显式指定它。简单方法调用的小步语义......
已有帐号?
无法登录?
社交帐号登录JS中的this用法详解
随着对的深入学习和使用,你会发现它里面包含了很多令人困惑的机制,比如对象、闭包、原型链继承等等,而这其中肯定包含令你现在或者曾经费解的,如果你不把心一横,花点时间还真不明白这个this的用法,下面这篇文章来详细探讨下:  1、this是啥?  简言之,this是中定义的众多关键字之一,它的特殊在于它自动定义于每一个函数域内,但是this倒地指引啥东西却让很多人张二摸不着头脑。这里我们留个小悬念,希望看完这篇文章了你能回答出来this到底指引个甚。  2、this有啥用?  那边观众又该为了,既然this这么难以理解,那么为个甚还要用它呢?我们来看个例子:&function&identify()&{
&&&&&return&this.name.toUpperCase();
&function&sayHello()&{
&&&&&var&greeting&=&&Hello,&I'm&&&+&identify.call(&this&);
&&&&&console.log(&greeting&);
&var&person1=&{
&&&&&name:&&Kyle&
&var&person2=&{
&&&&&name:&&Reader&
&identify.call(&person1);&//&KYLE
&identify.call(&person2);&//&READER
&sayHello.call(&person1);&//&Hello,&I'm&KYLE
&sayHello.call(&person2);&//&Hello,&I'm&READER  这段代码很简单,我们定义了两个函数,分别为identify和sayHello。并且在不同的对象环境下执行了它们,达到了复用的效果,而不用为了在不同的对象环境下执行而必须针对不同的对象环境写对应的函数了。简言之,this给函数带来了复用。那边客官又问了,我不用this一样可以实现,如:&function&identify(context)&{
&&&&&return&context.name.toUpperCase();
&function&sayHello(context)&{
&&&&&var&greeting&=&&Hello,&I'm&&&+&identify(&context);
&&&&&console.log(&greeting&);
&var&person1=&{
&&&&&name:&&Kyle&
&var&person2=&{
&&&&&name:&&Reader&
&identify(&person1);&//&KYLE
&identify(&person2);&//&READER
&sayHello(&person1);&//&Hello,&I'm&KYLE
&sayHello(&person2);&//&Hello,&I'm&READER  仔细一看,这位客官给出的解决方法的确也达到了类似的效果。赞一个!我想说的是,随着代码的增加,函数嵌套、各级调用等变得越来越复杂,那么传递一个对象的引用将变得越来越不明智,它会把你的代码弄得非常乱,甚至你自己都无法理解清楚。而this机制提供了一个更加优雅而灵便的方案,传递一个隐式的对象引用让代码变得更加简洁和复用。好了,知道了this的用处,那么再看看我们对它的误解。  3、关于this的误解  相信很多童鞋是学过其它语言的,在很多编程语言中都有this的机制,惯性思维把其它语言里对它的理解带到了JavaScript中。同时,由于this这个单词的理解导致了我们产生了对它各种各样的误解。所以,开始前,我们先澄清下对它的误解。  ??3.1 误解一:this引用function本身??  我们都知道,在函数里引用函数可以达到递归和给函数属性赋值的效果。而这在很多应用场景下显得非常有用。所以,很多人都误以为this就是指引function本身。例如:&function&fn(num)&{
&&&&&console.log(&&fn:&&&+&num&);
&&&&&//&count用于记录fn的被调用次数
&&&&&this.count++;
&fn.count&=&0;
&for&(i=0;&i&10;&i++)&{
&&&&&if&(i&&&5)&{
&&&&&&&&&fn(&i&);
&console.log(&fn.count&);&//&0&--&耶?咋不是4捏?  上面我们想要记录fn被调用的次数,可是明显fn被调用了四次但count仍然为0。咋回事捏?这里简单解释下,fn里第4行的自增隐式的创建了一个全局变量count,由于初始值为undefined,所以每一次自增其实依然不是一个数字,你在全局环境下打印count(window.count)输出的应该是NaN。而第6行定义的函数熟悉变量count依然没变,还是0。如果对这个执行结果不清楚的,欢迎去看我前些天的那篇博文(聊一下JS中的作用域scope和闭包closure scope和closure),在这里你只需要知道,this引用的是function这种理解是错误的就行。  这边就会又有人问了,既然this不是引用function,那么我要实现递归函数,该咋引用呢?这里简单回答下介个问题,两种方法:①函数体内用函数名来引用函数本身②函数体内使用arguments.callee来引用函数(不推荐)。那么既然第二种方法不推荐,匿名函数咋引用呢?用第一种,并且给匿名函数一个函数名即可(推荐)。  3.2 误解二:this引用的是function的词法作用域  这种误解欺骗的人可能更多一些。首先,澄清一下,this并没有引用function的词法作用域。的确JS的引擎内对词法作用域的实现的确像是一个对象,拥有属性和函数,但是这仅仅是JS引擎的一种实现,对代码来说是不可见的,也就是说词法作用域“对象”在JS代码中取不到。(关于词法作用域,如果不理解,可以参考之前的一篇博文《聊一下JS中的作用域scope和closure scope和closure》)。看个错误的例子:function&fn1()&{
&&&&var&a&=&2;
&&&&this.fn2();//以为this引用的是fn1的词法作用域
function&fn2()&{
&&&&console.log(&this.a&);
fn1();&//ReferenceError  上面的代码明显没有执行出想要的结果,从而可以看到this并没有引用函数的词法作用域。甚至,可以肯定的说,这个例子里fn2可以在fn1里正确执行都是偶然的(理解了词法作用域你就知道为什么这里执行不报错了)。  4、this到底跟啥有关?  好了,扯了那么多都没上干货,有的观众都开始关闭当前页开始离席了。这里,我们郑重声明:this跟函数在哪里定义没有半毛钱关系,函数在哪里调用才决定了this到底引用的是啥。也就是说this跟函数的定义没关系,跟函数的执行有大大的关系。所以,记住,“函数在哪里调用才决定了this到底引用的是啥”。  5、this机制的四种规则  this到底绑定或者引用的是哪个对象环境决定于函数被调用的地方。而函数的调用有不同的方式,在不同的方式中调用决定this引用的是哪个对象是由四种规则确定的。我们一个个来看。  5.1 默认绑定全局变量  这条规则是最常见的,也是默认的。当函数被单独定义和调用的时候,应用的规则就是绑定全局变量。如下: function&fn()&{
&&&&console.log(&this.a&);
var&a&=&2;
fn();&//&2&--&fn单独调用,this引用window  5.2 隐式绑定  隐式调用的意思是,函数调用时拥有一个上下文对象,就好像这个函数是属于该对象的一样。例如:function&fn()&{
&&&&console.log(&this.a&);
var&obj&=&{
&&&&fn:&fn
obj.fn();&//&2&--&this引用obj。  需要说明的一点是,最后一个调用该函数的对象是传到函数的上下文对象(绕懵了)。如:&function&fn()&{
&&&&&console.log(&this.a&);
&var&obj2&=&{
&&&&&a:&42,
&&&&&fn:&fn
&var&obj1&=&{
&&&&&a:&2,
&&&&&obj2:&obj2
&obj1.obj2.fn();&//&42&--&this引用的是obj2.  还有一点要说明的是,失去隐式绑定的情况,如下:&function&fn()&{
&&&&&console.log(&this.a&);
&var&obj&=&{
&&&&&a:&2,
&&&&&fn:&fn
&var&bar&=&obj.&//&函数引用传递
&var&a&=&&全局&;&//&定义全局变量
&bar();&//&&全局&  如上,第8行虽然有隐式绑定,但是它执行的效果明显是把fn赋给bar。这样bar执行的时候,依然是默认绑定全局变量,所以输出结果如上。 5.3 显示绑定  学过bind()\apply()\call()函数的都应该知道,它接收的第一个参数即是上下文对象并将其赋给。看下面的例子:&function&fn()&{
&&&&&console.log(&this.a&);
&var&obj&=&{
&fn.call(&obj&);&//&2  如果我们传递第一个值为简单值,那么后台会自动转换为对应的封装对象。如果传递为null,那么结果就是在绑定默认全局变量,如:&function&fn()&{
&&&&&&console.log(&this.a&);
&&var&obj&=&{
&&&&&&a:&2
&var&a&=&10;
&fn.call(&null);&//&10  5.4 new新对象绑定  如果是一个构造函数,那么用new来调用,那么绑定的将是新创建的对象。如:function&fn(a)&{
&&&&this.a&=&a;
var&bar&=&new&fn(&2&);
console.log(&bar.a&);//&2  注意,一般构造函数名首字母大写,这里没有大写的原因是想提醒读者,构造函数也是一般的而已。  6、结束语  读到现在,1中问的问题你该自己能回答上来了。上面介绍的四种关于this绑定的4中情况和规则,现实写代码的过程中肯定比这要多和复杂,但是无论多复杂多乱,它们都是混合应用上面的几个规则和情况而已。只要你的思路和理解是清晰的,那肯定没问题的。
评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
关注w3cmark
微信公众号
w3cmark_com

我要回帖

更多关于 js语法大全 的文章

 

随机推荐