摘要:然后将构造函数的原型设为,便实现了对象继承。首先,我们定义一个构造函数,并在其中定义一个局部变量。这里的是局部变量,其作用域仍然存在是闭包现象,而非对象属性。
Javascript是动态的,弱类型的,解释执行的程序设计语言。
Javascript极其灵活,支持多种程序设计范式:面向对象、指令式、函数式。JavaSCript最初被用于浏览器脚本,现在已经是所有主流浏览器的默认脚本语言。浏览器脚本的作用包括用户交互、DOM操作、以及与服务器通信。Node.js的流行已经将JavaScript从浏览器端引入到服务器端,并显示出卓越的并发性能。
Javascript 由 Netscape 浏览器首次引入到Web文档中。Javascript的出现使web文档变得更像动态的App,而不是静态的文档。现在主流的浏览器都有javascript支持。Javascript核心被标准化为ECMAScript。
JavaScript作为一门通用编程语言(general purpose),其语法、内置对象、以及工具库需要大量的精力才能掌握,但JavaScript有着直观的语法,是一门非常容易上手的编程语言。本章中介绍JavaScript最基本的语法,然后编写一个简单的Javascript程序。
1.Hello World使用你喜欢的文本编辑器,建立一个javascript文件(后缀命名为.js即可),输入以下的内容:
console.log("Hello, world!")
console为多数JavaScript的宿主环境都会提供的全局对象,它的log方法用来输出(到标准输出)一个字符串。为了运行这段程序,可以打开Chrome浏览器的开发者工具(右上角的设置按钮->更多工具->开发者工具),进入Console页面。
拷贝这段代码进去,按下回车,你会看到在控制台的输出:Hello, world!。
2.数据类型Javascript 是一门弱类型和动态类型的语言。弱类型意味着允许隐式类型转换,不同类型的变量间可以直接赋值和运算;动态类型则意味着只在运行时才会进行类型检查,于是包含错误的文件仍然能够得到执行,直到运行至包含类型错误的语句,JavaScript程序才异常退出。
Javascript中包含5种基本类型(primitive types):
字符串(String):其取值为字符序列。字符串可以用单引号或双引号分隔,二者完全等价。
var str1 = "str1", str2 = ""str1" is a string";
数字(Number):它是实数?整数?无符号数?这些都不需要考虑!Javascript中,数字就是数字!
var n = 1; n = n/3; // 0.33333...
布尔类型(Boolean):只有两种取值:true, false。
空(Null):该类型只有一个值可取,它就是null。在多数Javascript运行时中,null是一种特殊的object。
未定义(Undefined):该类型也只有一个值可取,它就是undefined。有趣的是,你可以把一个变量声明为未定义:
var foo = undefined;
除了基本数据类型,还有一种对象(object)类型,Object是JavaScript中所有其他对象的原型(如果你熟知Java等基于类继承的语言,可以理解为Object是其他所有对象的公共父类)。日期、数组、函数都是JavaScript内置的特殊对象。ECMAScript将对象定义为属性的集合(Collection),创建一个对象的语法就像创建一个集合:
var student = {name: "小明", age: 23};
我们看到:
所有的变量都是以var声明的,如果你忘记了写var,那么这个变量将成为整个运行时的全局变量。
另外,Javascript与C++使用同样的注释风格,即/**/用于多行注释,//用于单行注释。
3.对象Javascript是面向对象的编程语言,对象是javascript中最重要的概念。上一节我们通过一对大括号创建了一个对象:
var student = {name: "小明", age: 23};
如果你熟悉构造函数,JavaScript也支持这种方式:
function Student(name){ this.name = name; this.age = 23; } var student = new Student("小明"); student.school = "PKU";
在Javascript中,通过this来访问自己的属性。有趣的是,访问属性前不需声明:
如果直接读取未声明属性,会得到undefined;
如果直接写入未声明属性,则会声明并用指定的值初始化该属性。
如果你熟悉设计模式,你可能会需要这样的对象创建方式:
function StudentFactory(_school){ var school = _school; this.create = function(name, age){ return { name: name, age : age, school: school } } } var factory = new StudentFactory("PKU"); var student = factory.create("小明", 23);
上述代码中,首先声明了一个工厂对象(function是一种特殊的对象),并用school来配置该工厂。此后用该工厂生产一个学生对象:小明。
现在,你已经熟悉了Javascript中对象的创建。如果你曾开发过C++或者Java,你可能会关心Javascript中如何进行继承,以及实现多态。
不错,Javascript是面向对象语言。但没有类的声明和实例化机制,Javascript使用原型继承的方式(prototype)。看到下面的例子也许就清楚了:
// file: prototype.js var Person = { sayhi : function(){ console.log("hi! I"m", this.name) } }; function Student(name){ this.name = name; this.school = "pku"; } Student.prototype = Person; var student = new Student("alice"); // hi! I"m alice student.sayhi();
上述代码中,首先声明了Person对象,他有一个sayhi属性,该属性的值为function类型(还记得吗?函数是一种特殊的对象)。然后将构造函数Student的原型设为Person,便实现了对象继承。
4.函数prototype对象是个模板,要实例化的对象都以这个模板为基础(属性和方法都被传递给那个类的所有实例)。prototype是可以传递的,最终形成原型链。
JavaScript 最令人感兴趣的可能莫过于函数实际上是功能完整的对象,通过function来声明函数。在JavaScript中的函数是一级公民,这意味着函数和其他变量一样,可以被传参、赋值、以及返回。函数有如下几个默认属性:
1.length:参数个数
function func(arg1, arg2){} // 2 console.log(func.length)
2.toString:这是所有对象共有的方法,将会输出函数的源代码
// function func(arg1, arg2){} console.log(func.toString())5.arguments
在函数体中,JavaScript提供了一个特殊对象 arguments,它是当前函数被调用时传入的参数数组,通过访问arguments不仅可以访问所有实参,还可以获得实参的数目,从而实现其他编程语言中可变参数的机制:
/ file: arguments.js function sayHi(){ if(arguments.length == 1) console.log("I"m", arguments[0]); if(arguments.length == 2) console.log("I"m", arguments[0], "aged", arguments[1]); } // I"m alice sayHi("alice"); // I"m alice aged 23 sayHi("alice", 23);
6.call & applyJavascript并未提供函数重载、默认参数机制。但我们可以直接访问arguments参数列表,sayHi其实模仿了函数重载。
call和apply是函数对象的两个函数属性,一般用于对象冒充、包装或者代理。可能在教学中不会用到太多,但在JS库的开发中会经常用到。这两个函数的功能均为用一个对象去调用一个函数,而该函数并非该对象的属性,例如:
// file: call.js function sayHi(age){ console.log("I"m", this.name, "aged", age) } var student = { name: "alice" }; // I"m alice aged 23 sayHi.call(student, 23)
call的第一个参数是用作this的对象。其他参数都直接传递给函数自身。既然如此,如果我们希望实现一个自己的log函数,来包装console.log:
// file: log.js function log(){ var str = ""; for(var i = 0; i < arguments.length; i++){ str += " " + arguments[i] } console.log(str); } // a b c log("a", "b", "c");
这里我们不能使用call函数,因为我们不知道参数个数。这便是apply的用武之地:
// file: log.js function log(){ console.log.apply(this, arguments) } // a b c log("a", "b", "c");
apply接受的第二个参数为参数数组,而非call的参数列表。这便为上述的情况提供了便利。
7.回调与异步因Javascript最初运行于浏览器端,与服务器的通信必然要异步执行(否则,将会阻塞主控制流,此时浏览器会不响应用户操作)。于是,Javascript天生就是异步的,Node.js也是采用异步事件而大幅提高I/O密集型任务的效率。
异步是计算机在执行任务的过程中,某些任务可以独立于主控制流执行,使得主控制流得以继续执行,是一种非阻塞的控制方案。
在Javascript中有多种异步的实现方案,它们无一例外地需要回调函数。回调函数就是将函数作为参数传递到其他代码(例如:某一个异步任务),这一设计允许了该异步任务完成时执行传入的函数。例如:
// file: async.js function taskFinished(){ console.log("Task finished!") } setTimeout(taskFinished, 3000);
上述代码中,首先定义了一个任务完成时需要执行的函数taskFinished。setTimeout是Javascript提供的一个全局对象(还记得吗?函数是一种特殊的对象),它是一个计时器,在到达指定的时间后调用某个函数。上述例子中,在5000毫秒后运行taskFinished函数。
8.变量作用域与闭包Javascript的变量作用域不同于其他的主流编程语言。包括变量的定义方式、作用域的划分、作用持续时间等。
在javascript中使用赋值语句即可定义一个对象,而不需要对象声明(也不需要指定变量的类型)。使用var可以定义局部变量,而省略var则可以定义全局变量。例如:
// 定义局部变量 foo var foo = "bar" // 定义全局变量 bar bar = "foo
上述的全局变量作用域不是当前对象,也不是当前文件,而是整个运行时进程!实际项目中,应尽量避免引入全局变量。众所周知,全局变量会使得代码高度耦合、难以复用和维护、复杂化团队协作。
那么,局部变量的作用域是怎样的呢?局部作用域即当前函数,不同于C++或Java的当前代码块(以大括号分隔)。正因为javascript的这一点特殊性质,引出了javascript中的一个重要概念:闭包(closure)。闭包是指是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了它最初被创建的环境。
闭包之所以如此重要,是因为它完成了javascript的诸多面向对象特性:数据封装、运行时多态。我们看一个闭包:
// file: closure.js function Count(){ var num=0; this.add = function(){ console.log(num++); } } var c = new Count(); c.add(); c.add();
Count是函数,而函数是对象,对象可以有属性和方法。add是方法属性(类型为方法的属性),而num则只是函数的局部变量。
首先,我们定义一个构造函数Count,并在其中定义一个局部变量num。接着,我们调用该构造函数创建一个对象c,并调用两次它的add方法。不出所料,程序的输出将是:
0 1
你可能已经注意到:第二次调用add方法时,add中引用的num仍然保持着上次调用后的值。事实上,num是被add方法引用的一个自由变量,其作用域会一直跟随add而存在。
不要混淆局部变量和对象属性。这里的num是局部变量,其作用域仍然存在是闭包现象,而非对象属性。对象属性需要用this关键字来定义。
版权声明如果你希望进一步学习Javascript,Mozilla Developer和W3C School: Javascript教程都提供了很好文档。如果你愿意深究Javascript语法规则,请参考ECMAScript标准:ECMAScript-262。
本文由Harttle创作,转载需署名作者且注明文章出处
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/87727.html
摘要:所有全局对象函数以及变量均自动成为对象的成员。消息弹出窗口对象使用简单方便,但因其交互方式生硬,通常只用于调试。可以在中创建三种消息框警告框确认框提示框。习惯上,通过选择符得到的集合一般命名为以起始的字符串,例如。 avascript 等于 ECMAScript + 宿主环境。宿主环境提供了一系列的全局对象,例如Node.js提供的require, console等;浏览器提供的DOM...
摘要:简介是对象表示法的缩写是一种数据格式而不是一种编程语言用来表示结构化数据是的一个严格子集并不从属于很多编程语言都可以用数据格式语法语法可以表示以下三种类型的值简单值字符串数值布尔值但是不支持对象数组不支持变量函数对象实例简单值字符串数字布尔 JSON 简介 JSON是JavaScript Object Notation(JavaScript对象表示法)的缩写 JSON是一种数据格式,...
摘要:简介是的新增特性。我们统一把这些操作称为副作用,或者简称为作用。由于副作用函数是在组件内声明的,所以它们可以访问到组件的和。副作用函数还可以通过返回一个函数来指定如何清除副作用。目前为止,有两种主流方案来解决这个问题高阶组件和。 Hook 简介 Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。 us...
摘要:用声明的变量,其可用范围在当前执行上下文。在函数外声明的变量,其作用范围是全局。抛出语法错误错误信息未捕获的异常标识符已经被声明过。例如输出照例,命名规范指出我们应该用大写字母声明常量。为了让代码长期可维护,命名规范还是值得遵守的。 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。原文出处:https://dzone.com/articles/...
摘要:但是在中,可以通过关键字来实现类的继承的使用可以使得继承意义更加明确并且值得一提的是,如果你使用来定义的组件,那么可以在类的构造器里面,用简单的的声明方式来替代方法。 原文:The 10 min ES6 course for the beginner React Developer译者:Jim Xiao 著名的80/20定律可以用来解释React和ES6的关系。因为ES6增加了超过75...
阅读 968·2021-11-22 13:52
阅读 1411·2021-11-19 09:40
阅读 3020·2021-11-16 11:44
阅读 1206·2021-11-15 11:39
阅读 3797·2021-10-08 10:04
阅读 5214·2021-09-22 14:57
阅读 3073·2021-09-10 10:50
阅读 3133·2021-08-17 10:13