js闭包、原型、继承、作用域

作用域:

作用域是针对变量而言的,比如定义了一个函数啊a1,a1里面又定义一个子函数a2,此时就会有三个作用域  全局作用域--a1作用域--a2作用域

当a2查找变量时会先从自身的作用域开始查找,找不到就向上一级作用域a1查找,直到全局作用域,这就形成了一个作用域链

原型:

javascript中,一切皆对象,每个对象都会会有一个_propo_属性(浏览器自动创建),该属性指向它的原型,当一个对象查询一个属性的时候,自身没有就会根据_propo_向原型查找,直到object.prototype._propo_为null,这样就形成了一个原型链

prototype是什么呢?

我们直到我们可以通过一个构造函数创建一个类,prototype的作用就是让类的属性可以被继承,所以只有构造函数才有prototype这个属性

继承:

javascript中的继承是通过原型链来体现的。先看几句代码

以上代码中,f1是Foo函数new出来的对象,f1.a是f1对象的基本属性,f1.b是怎么来的呢?——从Foo.prototype得来,因为f1.__proto__指向的是Foo.prototype

访问一个对象的属性时,先在基本属性中查找,如果没有,再沿着__proto__这条链向上找,这就是原型链

那么我们在实际应用中如何区分一个属性到底是基本的还是从原型中找到的呢?大家可能都知道答案了——hasOwnProperty,特别是在for…in…循环中,一定要注意。

等等,不对! f1的这个hasOwnProperty方法是从哪里来的? f1本身没有,Foo.prototype中也没有,哪儿来的?

好问题。

它是从Object.prototype中来的,请看图:

对象的原型链是沿着__proto__这条线走的,因此在查找f1.hasOwnProperty属性时,就会顺着原型链一直查找到Object.prototype。

由于所有的对象的原型链都会找到Object.prototype,因此所有的对象都会有Object.prototype的方法。这就是所谓的“继承”。

当然这只是一个例子,你可以自定义函数和对象来实现自己的继承。

说一个函数的例子吧。

我们都知道每个函数都有call,apply方法,都有length,arguments,caller等属性。为什么每个函数都有?这肯定是“继承”的。函数由Function函数创建,因此继承的Function.prototype中的方法。不信可以请微软的Visual Studio老师给我们验证一下:

看到了吧,有call、length等这些属性。

那怎么还有hasOwnProperty呢?——那是Function.prototype继承自Object.prototype的方法。有疑问可以看看上一节将instanceof时候那个大图,看看Function.prototype.__proto__是否指向Object.prototype。

原型、原型链,大家都明白了吗?

JavaScript 闭包与类(原型链)之间的开发方式?

最近遇到一个问题.关于如何利用闭包开发与如何利用原型链开发.
自己看了一本书《JavaScript设计模式与开发实践》 里面有一章提到了高阶函数.而且在这本书很多设计模式都能利用闭包来实现.等等之类的.
自己在学习的过程中也一直不明白类(原型链)的开发与闭包的开发
比如用构造函数写个类
function Girl(name){
this.name=name
}
Girl.prototype.sayname=function(){console.log(this.name)}
这也可以用闭包来实现
var Girl=function(name){
var girlname=name;
var sayname=function(){
console.log(name)
}
return {
sayname:sayname
}
}
那么问题来了。

如何利用闭包来编写程序和如何利用原型链来编写程序,这两种编写模式有什么差别。如何写才是最佳的方式。在什么情况下使用原型链模式来编写?什么情况下使用闭包来编写?

这是个很宽泛的问题,利用闭包和原型能干什么事情。我从你题中的应用场景,分析下用原型和用闭包实现的不同点。
案例1:
function Girl(name){
this.name=name
}
Girl.prototype.sayname=function(){console.log(this.name)}
var a = new Girl('Lucy');
var b = new Girl('Lily');
案例2:
var Girl=function(name){
var sayname=function(){
console.log(name)
}
return {
sayname:sayname
}
}
var a = Girl('Lucy');
var b = Girl('Lily');
案例1中,a,b的结构如下图所示(一些无关的属性没有完全画出):


案例2中,a,b的结构如下图所示(一些无关的属性没有完全画出):

我们来对比下两者的区别以及原因:
1. 方案1中:构造出来的对象a、b,通过原型共享sayname方法;方案2中生成的对象a、b各有自己的属性方法sayname(空间上浪费)。这就是原型设计的初衷。我们通过这里也看到了自身属性和原型属性的区别(顺便说下可以通过hasOwnProperty属性来区分)。
2. 方案1中:构造出来的对象a、b各有自己的属性name,我们可以通过a.name,b.name来访问这个属性;方案2中,生成的对象a、b并没有属性name,而他们的方法属性sayname的作用域链上有name变量,在sayname方法里面可以访问name变量。我们看到方案1中的name属性具有面向对象中的公有属性的特性,而方案二中name具有面向对象中的私有属性的特性。

关于闭包,我在内网论坛写过一篇文章,有童鞋转载到csdn JS闭包 - JokerWILL ,有兴趣可以看下。

所以我们要了解原型和闭包的特性,了解使用原型和闭包会产生怎样不同的结果,根据我们的需求来灵活的使用。

题主这问题问得....
原型链是干什么用的,是共享属性和方法,是可以实现继承的
闭包是对变量和方法的封装,可以延迟使用外部变量和方法

构造函数上的方法是每个实例对象都有这个方法,彼此不同

原型链的方法是各个实例对象共享这个方法

首先明白概念是什么,能够干什么用,再说什么模式一类的东西,模式是大量实践总结出来的通用做法,js高级程序设计,一定多看几遍


原文地址:https://www.cnblogs.com/liangshuang/p/8477974.html