下面属于javascript对象的有:( )
A. Window
B. Document
C. Form
D. String
E. Navigator
解答:ACE
下面属于javascript对象的有:( )
A. Window
B. Document
C. Form
D. String
E. Navigator
解答:ACE
转载于:https://www.cnblogs.com/borter/p/9592765.html
作者 | Aparna Joshi 译者 | 王强 策划 | 李俊辰 原型(prototype)是 JavaScript 中每个对象都包含的一个属性(除非使用 Object.create(null) 来创建对象)。但是它的内部工作机制鲜为人知。原型属性的分配机制是一个重要的概念,利用它可以在 JavaScript 中应用继承。在理解原型之前,你必须了解 对象 的一些基本原理和用法。在本文中,我们将深入探讨在对象创建过程中是如何分配原型的,以及为什么这部分知识非常重要。
本文最初发布于 Aparna Joshi 网站,经原作者授权由 InfoQ 中文站翻译并分享。
什么是原型属性,它包含什么?使用任何可用方法创建的所有 JavaScript构造函数(constructor function) 都包含一个属性。这就是 原型 属性。这里很重要的是,原型属性本身就是一个对象。
我们来看一个例子以更好地理解这一点:
构造函数的原型属性可用于访问 / 修改方法,以及访问 / 修改在创建对象时分配的原型对象中存在的其他属性。
每个原型对象都有一个称为 构造器(constructor) 的属性。这个属性指向构造函数 (Constructor Function) 本身。
function Name(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.fullName = firstName + " " + lastName
}
var jensen = new Name("Jensen", "Ackles");
console.log(jensen);如果尝试访问包含对象 jensen 的所有属性的 console.log,我们将得到以下结果。
到这里发生过的事情原理是这样的:
Name 是一个构造函数。它包含 原型 属性。
这个原型属性有一个称为 constructor 的属性,该属性指向 Name 构造函数本身。可以将其他任何属性(attribute)添加到这个属性上。
使用 Name 构造器创建新对象 jensen 后,这个对象可以访问属于 Name 函数的所有属性,包括其原型。
可以使用 proto 对象从新对象 jensen 中访问 Name 构造函数的 原型。
由于 原型 本身是一个对象,因此它还包含一个 原型 属性。这样就创建了 原型链:
https://aparnajoshi.netlify.app/javascript-prototype-inner-workings-of-objects#prototype-chain
一些浏览器可以支持通过 proto 对象访问构造函数的原型。我们不建议在 JavaScript 编程中使用这个特性(该特性是非标准特性,可能无法在所有浏览器中都正常使用),但也可以用它在开发过程中快速检查原型链的运行状况。
proto 的替代方法包括 Object.getPrototypeOf() 或 objectInstance.constructor.prototype。对于上述示例来说,可以通过以下方式使用它来访问相同的原型属性:Object.getPrototypeOf(jensen);
jensen.constructor.prototype;原型链
我们通常是通过某些构造函数来创建对象的。如果未使用任何用户定义的构造器,则表示该对象是使用 JavaScript 的 Object Constructor(对象构造器) 创建的。这意味着我们创建的任何对象最终都将从 JavaScript 的对象构造器继承。
看一下下面创建的对象,看看它们的 proto 对象包含哪些内容。function Fruit() {
this.value = 10;
this.quantity = 35;
}
function Apple(name, color) {
this.name = name;
this.color = color
}
Apple.prototype = new Fruit();
var apple1 = new Apple("Apple", "Red");
console.log(apple1);如果我们检查对象 apple1 的内部属性,则可以观察到以下内容:
原型的使用:继承和内置方法
对象 apple1 包含两个主要属性:name 和 color。这些属性的值与在创建过程中分配给它们的值是一样的。
对象 apple1 的 proto 属性指向 Fruit 对象的实例。反过来,这又包含另外两个属性:value 和 quantity。
如果检查 Fruit 实例的 proto 属性,我们会发现它最终指向 JavaScript 的 Object 的原型。
当一个属性不直接存在于一个对象上时,JavaScript 会沿着 原型链 向上寻找,以在其最近的原型中找到该属性。就像 JavaScript 的作用域链一样,原型链也会不断上升,直到到达 Object.prototype 为止。
原型在 JavaScript 中广泛用于实现继承。传统上,JavaScript 仅用于脚本编写,并且不需要像其他语言一样提供面向对象的编程特性。但是,原型的概念可用来将方法和属性从一个构造函数传递到另一个构造函数。
考虑以下示例:function Fruit() {
this.value = 10;
this.quantity = 35;
}
Fruit.prototype.setValue = function(value) {
this.value = value;
}
function Apple(name, color) {
this.name = name;
this.color = color
}
Apple.prototype = new Fruit();
var apple1 = new Apple("Apple", "Red");
apple1.setValue(20);
console.log(apple1.name); // Apple
console.log(apple1.value); // 20
console.log(apple1.quantity); // 35在上面的示例中,即使新对象 apple1 不具有 value 和 quantity 属性,我们仍然可以访问它们。需要注意的是,添加到 Fruit 构造函数 的原型属性上的 setValue 方法也可以通过对象 apple1 访问。这就是在 JavaScript 中实现继承的方式。
使用任何构造器创建对象时,它都会附带某些可应用于对象的内置方法。其中一些内置方法包括 hasOwnProperty()、isPrototypeOf()、propertyIsEnumerable()、toLocaleString()、toString() 和 valueOf()。这些内置方法可用于所有对象。这是因为 JavaScript 中的所有对象都从 Object.prototype 继承属性和方法。
所有内置的构造器,例如 Array()、Number() 和 String() 等,都是从 JavaScript 的 Object 构造器创建的,并且它们的原型也分配给 Object.prototype。
原型存在的一些问题JavaScript 中的原型有很多用途,它可用于继承父函数的方法,还可以用于抽象数据层,并仅公开 getter 和 setter 方法来操作属于各种对象的值。但原型也有其缺点。原型对象上添加的所有属性,对于使用其 构造函数 创建的对象的每个实例都是通用的。对于其中任一属性的任何更改都将反映在所有对象中。
考虑以下示例:function Apple(name, color) {
this.name = name;
this.color = color
}
Apple.prototype.value = 20;
var apple1 = new Apple("Apple", "Red");
var apple2 = new Apple("Apple2", "Wheatish Red");
console.log(apple1.name); // Apple
console.log(apple1.value); // 20
console.log(apple2.value); // 20
Apple.prototype.value = 40;
console.log(apple1.value); // 40
console.log(apple2.value); // 40
apple1.value = 30;
console.log(apple1.value); // 30
console.log(apple2.value); // 40在上面的示例中,直接在构造器原型上进行的更改会反映在其所有对象中;但是,当更改对象 apple1 内部的属性 value 时,这一更改就不会反映在其他对象中。这是因为 apple1 现在已经创建了自己的属性 value,并且从这个实例开始,apple1.value 将始终引用为其自身的属性 value,而不是继承的属性。
为了解决这个问题,可以实现一个 构造器 - 原型 模式的组合。可以使用 构造函数 让属于该对象的数据值保持私有和唯一。那些可在所有对象之间共享的操作数据通用方法,可以添加到 原型对象 上。
我希望这篇文章能够帮助读者详细了解原型属性及其用法。如果你对本文中描述的概念有任何疑问,请随时与我联系:
https://twitter.com/aparna_joshi_
延伸阅读https://aparnajoshi.netlify.app/javascript-prototype-inner-workings-of-objects
JavaScript 作用域
- JS 异常
- JS Hoisting
作用域指的是您有权访问的变量集合。
JavaScript 函数作用域
在 JavaScript 中有两种作用域类型:
- 局部作用域
- 全局作用域
JavaScript 拥有函数作用域:每个函数创建一个新的作用域。
作用域决定了这些变量的可访问性(可见性)。
函数内部定义的变量从函数外部是不可访问的(不可见的)。
局部 JavaScript 变量
在 JavaScript 函数中声明的变量,会成为函数的局部变量。
局部变量的作用域是局部的:只能在函数内部访问它们。
实例
// 此处的代码不能使用 carName 变量function myFunction() { var carName = "porsche"; // 此处的代码能使用 carName 变量}
由于只能在函数内部识别局部变量,因此能够在不同函数中使用同名变量。
在函数开始时会创建局部变量,在函数完成时会删除它们。
全局 JavaScript 变量
函数之外声明的变量,会成为全局变量。
全局变量的作用域是全局的:网页的所有脚本和函数都能够访问它。
实例
var carName = " porsche";// 此处的代码能够使用 carName 变量function myFunction() { // 此处的代码也能够使用 carName 变量}
JavaScript 变量
在 JavaScript 中,对象和函数也是变量。
作用域决定了从代码不同部分对变量、对象和函数的可访问性。
自动全局
如果您为尚未声明的变量赋值,此变量会自动成为全局变量。
这段代码将声明一个全局变量 carName,即使在函数内进行了赋值。
实例
myFunction();// 此处的代码能够使用 carName 变量function myFunction() { carName = "porsche";}
严格模式
所有现代浏览器都支持以“严格模式”运行 JavaScript。
您将在本教程稍后的章节学习更多如何使用严格模式的知识。
在“严格模式”中不会自动创建全局变量。
HTML 中的全局变量
通过 JavaScript,全局作用域形成了完整的 JavaScript 环境。
在 HTML 中,全局作用域是 window。所有全局变量均属于 window 对象。
实例
var carName = "porsche";// 此处的代码能够使用 window.carName
警告
除非有意为之,否则请勿创建全局变量。
您的全局变量(或函数)能够覆盖 window 变量(或函数)。
任何函数,包括 window 对象,能够覆盖您的全局变量和函数。
JavaScript 变量的有效期
JavaScript 变量的有效期始于其被创建时。
局部变量会在函数完成时被删除。
全局变量会在您关闭页面是被删除。
一、JavaScript历史
- 1995年 网景招募了Brendan Eich,艾克在1995年5月花了十天时间就把原型设计出来,网景为了让这门语言搭上Java这个编程语言“热词”,将其改名为JavaScript
Brendan Eich
- 1996年8月,IE3发布,微软发布JScript,浏览器大战开始
- 1996年11月,网景向ECMA(欧洲极端及制造商协会)提交语言标准
- ECMAScript标准的制定:
- 1997年6月,ECMA以JavaScript语言为基础制定了ECMAScript标准,第一版发布
- 1999年12月,第三版发布,该版本使用最广
- 第四版流产
- 2009年12月,第五版发布
- 2015年6月,第六版发布,新浏览器都支持
- 之后每年发布一版,版本号以年份命名
二、JavaScript概论
- 完整的JavaScript包括以下几个部分:
- ECMAScript:描述了该语言的语法和基本对象
- 文档对象模型(DOM):描述处理网页内容的方法和接口
- 浏览器对象模型(BOM):描述与浏览器进行交互的方法和接口
- JavaScript的基本特点为:
- 一种解释性脚本语言(代码不进行预编译)。
- 主要用来向HTML页面添加交互行为。
- 可以直接嵌入HTML页面,也可以写成单独的js文件,这样有利于结构和行为的分离。
- JavaScript常用来完成以下任务:
- 在HTML页面中嵌入动态文本
- 对浏览器事件作出响应
- 读写HTML元素
- 在数据被提交到服务器之前验证数据
- 检测访客的浏览器信息
- 控制cookies,包括创建和修改等
JavaScript的10个设计缺陷
- 不适合开发大型项目程序,没有名称空间(namespace),很难模块化;
2. Javascript提供的标准函数库非常小,只能完成一些基本操作,很多功能都不具备;
3. null和undefined两者非常容易混淆,null属于对象(object)的一种,表示对象为空,undefined是一种数据类型,表示未定义。
typeof
4. 难以控制全局变量:任何一个函数内部都可以生成全局变量,大大加剧了程序的复杂性;
5. 若忘记写分号,解释器自动在行末插入分号,常常导致一些错误;
function(){ return { i=1 }; }
上面这个函数根本无法达到预期的结果,返回值不是一个对象,而是undefined。
这也是为什么,老师们会说 return 后面不能换行的原因。6. 加号运算符:+号作为运算符,有两个含义,可以表示数字与数字的和,也可以表示字符与字符的连接。
1
如果一个操作项是字符,另一个操作项是数字,则数字自动转化为字符。
"1"
7. NaN是一种数字,表示超出了解释器的极限。
NaN 不等于任何值,包括它本身8. 数组和对象的区分
由于Javascript的数组也属于对象(object),所以要区分一个对象到底是不是数组,相当麻烦,下面代码是一种方式:
if
9. "=="和"==="
"=="用来判断两个值是否相等。当两个值类型不同时,会发生自动转换,得到的结果非常不符合直觉,推荐任何时候都使用"==="(精确判断)比较符
10. 基本类型的包装对象
Javascript的三种基本数据类型(字符串、数字和布尔值)都有相应的建构函数,可以生成字符串对象、数字对象和布尔值对象。
new
但容易造成混淆
alert
参考:
维基百科zh.wikipedia.orgJavascript诞生记 - 阮一峰的网络日志www.ruanyifeng.comJavascript的10个设计缺陷 - 阮一峰的网络日志www.ruanyifeng.com