您的位置:首页 > Web前端 > JavaScript

js的原型和对象

2016-01-25 22:33 661 查看
为了了解更深层次的js,不光我们了解一个语言的内部,而且我们要掌握这门语言的设计思想,这样才能学习其他语言的时候,掌握的更快。

js这门语言可以说一切都是对象,对象只有属性,就连那些方法也可以说是属性,要不然我们定义函数的时候可以用键值对的形式进行,下面我们看一些例子`

function show(x) {

console.log(typeof(x));    // undefined
console.log(typeof(10));   // number
console.log(typeof('abc')); // string
console.log(typeof(true));  // boolean

console.log(typeof(function () { }));  //function

console.log(typeof([1, 'a', true]));  //object
console.log(typeof ({ a: 10, b: 20 }));  //object
console.log(typeof (null));  //object
console.log(typeof (new Number(10)));  //object
}
show();


在这里可以看到除了基本类型,所有的引用类型都是对象,函数也是对象。

js的对象其实就是若干属性的集合,比如`

var fn = function () {
alert(100);
};
fn.a = 10;
fn.b = function () {
alert(123);
};
fn.c = {
name: "王福朋",
year: 1988
};


在这里可以把一些值直接用点,也就是说相当于是这个对象的一个属性添加到这个对象上面去,

切记一切引用类型都是对象,对象是属性的集合

在理解了上面这个重要的知识点之后,就说说函数和对象之间的关系,其实对象就是通过函数来实现的,但是有人说这样也可以:

var obj = {"a":"dsaf","b":"dsafsad"}
var arr = [1,"dsfa"];


上面的例子虽说不是标准的例子,但是其实是语言为了我们写起来更加的方便,其实他们两个也是通过函数创建的,真实的代码应该是这样的:

var obj = new Object();
obj.a  = "dsaf";
obj.b = "dsafsad";
var arr = new Array();
arr[0] = 1;
arr[1] = "dsfa";


而其中Object和Array都是函数

现在出现一个问题,对象是通过函数来创建的,但是函数又是另外一种对象,

我们可以都知道一个对象的prototype的constructor就是这个对象本身,我们看这一张图

这里的图就很形象的表现出他们之间的关系,是绕了一圈的样子,在这里我是看到别人的一篇文章用jquery中的一个例子进行解释的。

var $div = $('div');
$div.attr('myName', '王福朋');
myjQuery.prototype.attr = function () {
//……
};
$('div') = new myjQuery();


如果没看懂看下面这段代码:

function Fn() { }
Fn.prototype.name = '王福朋';
Fn.prototype.getYear = function () {
return 1988;
};

var fn = new Fn();
console.log(fn.name);
console.log(fn.getYear());


因为每一对象都有一个隐藏的属性“proto”,

这个属性引用了创建这个对象的函数的prototype即

fn.__proto__ === Fn.prototype


这里的proto_为隐式原型。

下面来说一个比价细但是又对js了解有很大帮助的操作符“instanceof”他的作用机制是Instanceof的判断队则是:沿着A的_proto_这条线来找,同时沿着B的prototype这条线来找,如果两条线能找到同一个引用,即同一个对象,那么就返回true。如果找到终点还未重合,则返回false。

重点就这样被这位老朋友给引出来了——继承——原型链。

即,instanceof表示的就是一种继承关系,或者原型链的结构。

js中也有继承,在这里说是因为,js的继承是通过原型链来体现的。

下面说一下js的赋值过程:

有三句话好好理解:

** 变量、函数表达式——变量声明,默认赋值为undefined;

this——赋值;

函数声明——赋值;

这三种数据的准备情况我们称之为“执行上下文”或者“执行上下文环境”。**

上下文有个通俗的定义:

执行上下文环境——在执行代码之前,把将要用到的所有的变量都事先拿出来,有的直接赋值了,有的先用undefined占个空。

对于this要好好理解

在函数中this到底取何值,是在函数真正被调用执行的时候确定的,函数定义的时候确定不了

如果函数对象作为一个属性的时候,那么这时的this指向的是这个对象,

其实,不仅仅是构造函数的prototype,即便是在整个原型链中,this代表的也都是当前对象的值。

还有一个非常重要的知识点:js没有块级作用域例如:

var i = 10;
if(i>1){
var name = "sufubo";
}
console.log(name);
//sufubo


虽然在里面声明了变量,但是都可以访问到,所以变量要在一开始就声明好,以免发生歧义。

作用域有上下级的关系,上下级关系的确定就看函数是在哪个作用域下创建的。例如,fn作用域下创建了bar函数,那么“fn作用域”就是“bar作用域”的上级。

作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突。

作用域只是一个“地盘”,一个抽象的概念,其中没有变量。要通过作用域对应的执行上下文环境来获取变量的值。同一个作用域下,不同的调用会产生不同的执行上下文环境,继而产生不同的变量的值。所以,作用域中变量的值是在执行过程中产生的确定的,而作用域却是在函数创建时就确定了。

所以,如果要查找一个作用域下某个变量的值,就需要找到这个作用域对应的执行上下文环境,再在其中寻找变量的值

要到创建这个函数的那个作用域中取值——是“创建”,而不是“调用”,切记切记——其实这就是所谓的“静态作用域”。

讲到自由变量跨作用域取值时,曾经强调过:要去创建这个函数的作用域取值,而不是“父作用域”

什么是闭包

你只需要知道应用的两种情况即可——函数作为返回值,函数作为参数传递。

上面是我看的文章中好的摘抄下来,但是要想成为自己的东西,感觉还是要用自己的话说出来比较好,js的原型和闭包本来关系就很紧密,首先要了解好原型,他的原型和其他语言的继承比较类似,这里有牵扯到原型链的问题,原型链就是函数在创建的时候,产生的,他是一环套一环的,就比如栈一样,会有不用的上下文执行环境,不同的活动对象,要注意不同的活动对象,也能找到当前正确的运行结果,这里就有一个知识点就是函数的作用域是在他创建的时候就定义好的,他的上下文环境就是定义他的时候,有一些变量,没有就是undefined,所以要找函数的上下文要去他定义的时候去找,而不是使用的时候去找,我们要理解一个概念,有些传递的参数,只能是传递时才能确定的要运行时才能知道,每个函数就像是一个地盘,函数就是产生作用域的地方,也是对象的产生地方,每个函数就是右一系列属性组成的,当时属性的时候,this就是调用当前的那个属性的对象,如果是普通函数的话就是window,还有以前一直不理解的闭包,其实就是一个是把函数当作返回值的函数,另一个是把函数作为参数传递,这样的才叫做闭包。这有一个鸡生蛋和蛋生鸡的问题,就是js一切都是对象,对象是通过函数创建的,函数也是一种对象,要理解这个跟原型离不开,函数都有一个prototype属性,指向的是他的父类,但是这个属性又有一个construct属性,又指回的是这个函数的自己。还有函数都有一个隐式的属性proto他是创建这个对象的那个对象的引用的原型。也总结这么多,后面有的话再补充。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  函数 设计 语言 对象