原型是一个对象,其他对象可以通过它实现属性继承

原型链:每个对象都会在其内部初始化一个属性,就是__proto__,当我们访问一个对象的属性 时,如果这个对象内部不存在这个属性,那么他就会去__proto__里找这个属性,这个__proto__又会有自己的__proto__,于是就这样 一直找下去,也就是我们平时所说的原型链的概念。

按照标准,__proto__是不对外公开的,也就是说是个私有属性,但是部分浏览器的引擎将他暴露了出来成为了一个共有的属性,让我们可以对外访问和设置。

对象(Object)

JavaScript中对象的创建有以下几种方式:

(1)使用内置对象

(2)使用JSON符号

(3)自定义对象构造

【内建对象】:通过JavaScript语言原生对象的构造方法,实例化出一个新的对象。

1,JavaScript语言原生对象(语言级对象),如String、Object、Function、Array 等;

2,JavaScript运行期的宿主对象(环境宿主级对象),如window、document、body等。

var str = new String("实例初始化String");
var str1 = "直接赋值的String";
var func = new Function("x","alert(x)");//示例初始化func
var o = new Object();//示例初始化一个Object

【JSON (JavaScript Object Notation)】即JavaScript对象命名,是一种轻量级的数据交换格式,易于阅读和编写,易于及其解析和生成。JSON是完全独立于语言的文本格式,因此成为数据交换的理想格式。

JSON有两种构建方式:

两种结构:

 一个对象,var o={"name":"小明","id":123456,"score":2000,"time":"1990-08-20"};
一个数组,var olist=[{"name":"小明","id":123456,"score":2000,"time":"1990-08-20"},{"name":"小宏","id":123456,"score":2000,"time":"1990-08-20"}]; var person=new Object();
person.name="lq";
person.age="21";
person.say=function(){
alert(this.name);
}; 等价于;
var person={
name:"zhangsan",
age:23,
say:function(){
alert(this.name);
}
}; var json = [];
var person = {};
person.id= "1";
person.name = "小明";
json.push(person ); JSON字符串:var str1 = '{ "name": "cxh", "sex": "man" }'; JSON对象:var str2 = { "name": "cxh", "sex": "man" };
一、JSON字符串转换为JSON对象
var str = '{ "name": "cxh", "sex": "man" }';
var obj = eval('(' + str + ')');
或者 var obj = $.parseJSON(str); //已经过时,不建议使用
或者 var obj = JSON.parse(str); 二、可以运用 toJSONString()或者全局要领 JSON.stringify()将JSON对象转化为JSON字符串 JSON对象解析为字符串:
情景1:jQuery插件支持的转换方式:
$.parseJSON( jsonstr ); //jQuery.parseJSON(jsonstr),可以将json字符串转换成json对象 情景2:浏览器支持的转换方式(Firefox,chrome,opera,safari,ie9,ie8)等浏览器:
JSON.parse(jsonstr); //可以将json字符串转换成json对象;
JSON.stringify(jsonobj); //可以将json对象转换成json对符串;
注:ie8(兼容模式),ie7和ie6没有JSON对象,推荐采用JSON官方的方式,引入json.js。 情景3:Javascript支持的转换方式:
eval('(' + jsonstr + ')'); //可以将json字符串转换成json对象,注意需要在json字符外包裹一对小括号 情景4:JSON官方的转换方式:[http://www.json.org/](http://www.json.org/)
提供了一个json.js,这样ie8(兼容模式),ie7和ie6就可以支持JSON对象以及其stringify()和parse()方法; 

创建对象

使用Object构造函数或对象字面量都可以创建对象,但缺点是创建多个对象时,会产生大量的重复代码,因此下面介绍可解决这个问题的创建对象的方法

1、工厂模式
function createPerson(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.getName = function () {
return this.name;
}
return o;//使用return返回生成的对象实例
}
var person = createPerson('Jack', 19, 'SoftWare Engineer');
创建对象交给一个工厂方法来实现,可以传递参数,但主要缺点是无法识别对象类型,因为创建对象都是使用Object的原生构造函数来完成的。
2、构造函数模式
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.getName = function () {
return this.name;
}
}
var person1 = new Person('Jack', 19, 'SoftWare Engineer'); 3、原型模式
function Person(){
}
Person.prototype.name = 'Jack';//使用原型来添加属性
Person.prototype.age = 29;
Person.prototype.getName = function(){
return this.name;
}
var person1 = new Person();
alert(person1.getName());//Jack
var person2 = new Person();
alert(person1.getName === person2.getName);//true;共享一个原型对象的方法 4、组合构造函数及原型模式
目前最为常用的定义类型方式,是组合构造函数模式与原型模式。构造函数模式用于定义实例的属性,而原型模式用于定义方法和共享的属性。结果,每个实例都会有自己的一份实例属性的副本,但同时又共享着对方方法的引用,最大限度的节约内存。此外,组合模式还支持向构造函数传递参数,可谓是集两家之所长。 function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.lessons = ['Math', 'Physics'];
}
Person.prototype = {
constructor: Person,//原型字面量方式会将对象的constructor变为Object,此外强制指回Person
getName: function () {
return this.name;
}
}
var person1 = new Person('Jack', 19, 'SoftWare Engneer');
person1.lessons.push('Biology');
var person2 = new Person('Lily', 39, 'Mechanical Engneer');
alert(person1.lessons);//Math,Physics,Biology
alert(person2.lessons);//Math,Physics
alert(person1.getName === person2.getName);//true,//共享原型中定义方法 5、动态原型模式
组合模式中实例属性与共享方法(由原型定义)是分离的,这与纯面向对象语言不太一致;动态原型模式将所有构造信息都封装在构造函数中,又保持了组合的优点。其原理就是通过判断构造函数的原型中是否已经定义了共享的方法或属性,如果没有则定义,否则不再执行定义过程。该方式只原型上方法或属性只定义一次,且将所有构造过程都封装在构造函数中,对原型所做的修改能立即体现所有实例中: function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.lessons = ['Math', 'Physics'];
}
if (typeof this.getName != 'function') {//通过判断实例封装
  Person.prototype = {
    constructor: Person,//原型字面量方式会将对象的constructor变为Object,此外强制指回Person
    getName: function () {
      return this.name;
    }
  }
}
var person1 = new Person('Jack', 19, 'SoftWare Engneer');
person1.lessons.push('Biology');
var person2 = new Person('Lily', 39, 'Mechanical Engneer');
alert(person1.lessons);//Math,Physics,Biology
alert(person2.lessons);//Math,Physics
alert(person1.getName === person2.getName);//true,//共享原型中定义方法 原型
原型是指向原型对象的,这个原型对象与构造函数没有太大关系,唯一的关系是函数的prototype是指向这个原型对象!而基于构造函数创建的对象实例也包含一个内部指针为:[[prototype]]指向原型对象。 实例属性或方法的访问过程是一次搜索过程: 首先从对象实例本身开始,如果找到属性就直接返回该属性值;
如果实例本身不存在要查找属性,就继续搜索指针指向的原型对象,在其中查找给定名字的属性,如果有就返回;
基于以上分析,原型模式创建的对象实例,其属性是共享原型对象的;但也可以自己实例中再进行定义,在查找时,就不从原型对象获取,而是根据搜索原则,得到本实例的返回;简单来说,就是实例中属性会屏蔽原型对象中的属性; 原型与in操作符 一句话:无论原型中属性,还是对象实例的属性,都可以使用in操作符访问到;要想判断是否是实例本身的属性可以使用object.hasOwnProperty(‘attr’)来判断; 原生对象中原型 原生对象中原型与普通对象的原型一样,可以添加/修改属性或方法,如以下代码为所有字符串对象添加去左右空白原型方法: String.prototype.trim = function(){
return this.replace(/^\s+/,'').replace(/\s+$/,'');
}
var str = ' word space ';
alert('!'+str.trim()+'!');//!word space!
原型模式的缺点,它省略了为构造函数传递初始化参数,这在一定程序带来不便;另外,最主要是当对象的属性是引用类型时,它的值是不变的,总是引用同一个外部对象,所有实例对该对象的操作都会其它实例: function Person() {
}
Person.prototype.name = 'Jack';
Person.prototype.lessons = ['Math','Physics'];
var person1 = new Person();
person1.lessons.push('Biology');
var person2 = new Person();
alert(person2.lessons);//Math,Physics,Biology,person1修改影响了person2

面向对象:

面向对象的语言有一个标志,即拥有类的概念,抽象实例对象的公共属性与方法,基于类可以创建任意多个实例对象,一般具有封装、继承、多态的特性!但JS中对象与纯面向对象语言中的对象是不同的,ECMA标准定义JS中对象:无序属性的集合,其属性可以包含基本值、对象或者函数。可以简单理解为JS的对象是一组无序的值,其中的属性或方法都有一个名字,根据这个名字可以访问相映射的值(值可以是基本值/对象/方法)。

Prototype(显式原型)

每一个函数在创建之后都会拥有一个名为prototype的属性,这个属性指向函数的原型对象。

Note:通过Function.prototype.bind方法构造出来的函数是个例外,它没有prototype属性。

显式原型的作用:用来实现基于原型的继承与属性的共享。


__ proto __ (隐式原型)

JavaScript中任意对象都有一个内置属性[[prototype]],在ES5之前没有标准的方法访问这个内置属性,但是大多数浏览器都支持通过__proto__来访问。ES5中有了对于这个内置属性标准的Get方法Object.getPrototypeOf(). Note: Object.prototype 这个对象是个例外,它的__proto__值为null

隐式原型的作用:构成原型链,同样用于实现基于原型的继承。举个例子,当我们访问obj这个对象中的x属性时,如果在obj中找不到,那么就会沿着__proto__依次查找。

__proto__的指向:

三种方式:(1)对象字面量的方式 (2)new 的方式 (3)ES5中的Object.create() 但是我认为本质上只有一种方式,也就是通过new来创建。为什么这么说呢,首先字面量的方式是一种为了开发人员更方便创建对象的一个语法糖,本质就是 var o = new Object(); o.xx = xx;o.yy=yy; 再来看看Object.create(),这是ES5中新增的方法,在这之前这被称为原型式继承,

以上两种情况都等于完全重写了Foo.prototype,所以Foo.prototype.constructor也跟着改变了,于是乎constructor这个属性和原来的构造函数Foo()也就切断了联系。

  1. instanceof

    instanceof 操作符的内部实现机制和隐式原型、显式原型有直接的关系。instanceof的左值一般是一个对象,右值一般是一个构造函数,用来判断左值是否是右值的实例。它的内部实现原理是这样的: //设 L instanceof R

    //通过判断

    L.proto.proto ..... === R.prototype ?

    //最终返回true or false

    也就是沿着L的__proto__一直寻找到原型链末端,直到等于R.prototype为止。知道了这个也就知道为什么以下这些奇怪的表达式为什么会得到相应的值了 Function instanceof Object // true

    Object instanceof Function // true

    Function instanceof Function //true

    Object instanceof Object // true

    Number instanceof Number //false

作者:苏墨橘

链接:https://www.zhihu.com/question/34183746/answer/59043879

来源:知乎

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

自定义对象   1.  默认情况下:function Foo(){}
var foo = new Foo()
Foo.prototype.__proto__ === Object.prototype //true 理由同上
2. 其他情况: (1) function Bar(){}
//这时我们想让Foo继承Bar
Foo.prototype = new Bar()
Foo.prototype.__proto__ === Bar.prototype //true
(2)//我们不想让Foo继承谁,但是我们要自己重新定义Foo.prototype
Foo.prototype = {
a:10,
b:-10
}
//这种方式就是用了对象字面量的方式来创建一个对象,根据前文所述
Foo.prototype.__proto__ === Object.prototype 作者:苏墨橘
链接:https://www.zhihu.com/question/34183746/answer/59043879
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

prototype和__ proto __的区别:

prototype是函数才具有的属性; __ proto __ 是每个对象都有的属性,但是 __ proto __ 不是一个规范属性,只是部分浏览器实现了此属性,对应的标准属性是[[Prototype]]

大多数情况下, proto 可以理解为“构造器的原型” ,即: __ proto __ === .constructor.prototype,但是 如果一个对象是通过Object.create函数构造出来的,那其__proto__就不一定是.constructor.prototype。


var a = {};
console.log(a.prototype); //undefined
console.log(a.__proto__); //Object {} var b = function(){}
console.log(b.prototype); //b {}
console.log(b.__proto__); //function() {}

首先,要明确几个点:1.在JS里,万物皆对象。方法(Function)是对象,方法的原型(Function.prototype)是对象。因此,它们都会具有对象共有的特点。即:对象具有属性__proto__,可称为隐式原型,一个对象的隐式原型指向构造该对象的构造函数的原型,这也保证了实例能够访问在构造函数原型中定义的属性和方法。2.方法(Function)方法这个特殊的对象,除了和其他对象一样有上述_proto_属性之外,还有自己特有的属性——原型属性(prototype),这个属性是一个指针,指向一个对象,这个对象的用途就是包含所有实例共享的属性和方法(我们把这个对象叫做原型对象)。原型对象也有一个属性,叫做constructor,这个属性包含了一个指针,指回原构造函数。好啦,知道了这两个基本点,我们来看看上面这副图。1.构造函数Foo()构造函数的原型属性Foo.prototype指向了原型对象,在原型对象里有共有的方法,所有构造函数声明的实例(这里是f1,f2)都可以共享这个方法。2.原型对象Foo.prototypeFoo.prototype保存着实例共享的方法,有一个指针constructor指回构造函数。3.实例f1和f2是Foo这个对象的两个实例,这两个对象也有属性__proto__,指向构造函数的原型对象,这样子就可以像上面1所说的访问原型对象的所有方法啦。另外:构造函数Foo()除了是方法,也是对象啊,它也有__proto__属性,指向谁呢?指向它的构造函数的原型对象呗。函数的构造函数不就是Function嘛,因此这里的__proto__指向了Function.prototype。其实除了Foo(),Function(), Object()也是一样的道理。原型对象也是对象啊,它的__proto__属性,又指向谁呢?同理,指向它的构造函数的原型对象呗。这里是Object.prototype.最后,Object.prototype的__proto__属性指向null。总结:1.对象有属性__proto__,指向该对象的构造函数的原型对象。2.方法除了有属性__proto__,还有属性prototype,prototype指向该方法的原型对象。


对象&内置对象& 对象构造 &JSON&__proto__和prototype的更多相关文章

  1. js中内置有对象

    statpot:使用mongo+bootstrap+highcharts做统计报表 最近做了一个统计项目,这个统计项目大致的需求是统计接口的访问速度.客户端会调用一个接口来记录接口的访问情况,我的需求 ...

  2. 浏览器扩展系列————给MSTHML添加内置脚本对象【包括自定义事件】

    原文:浏览器扩展系列----给MSTHML添加内置脚本对象[包括自定义事件] 使用场合: 在程序中使用WebBrowser或相关的控件如:axWebBrowser等.打开本地的html文件时,可以在h ...

  3. 内置3D对象-Unity3D游戏开发培训

    内置3D对象-Unity3D游戏开发培训 作者:Jesai 2018-02-12 19:21:58 五大面板: -Hierachy:当前场景中的物体 图 1-1 -Project:项目中的所有资源 图 ...

  4. 对象内置的方法/内置的 Symbol 值

    内置的 Symbol 值 除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法. Symbol.hasInstance 对象的Symbo ...

  5. JavaScript本地对象 内置对象 宿主对象

          在ECMAScript中,所有对象并非同等创建的. 一般来说,可以创建并使用的对象有3种:本地对象.内置对象和宿主对象. 1. 本地对象 ECMA-262把本地对象(native obje ...

  6. WeixinJSBridge:微信浏览器内置JavaScript 对象

    微信公众平台开始支持前端网页,大家可能看到很多网页上都有分享到朋友圈,关注微信等按钮,点击它们都会弹出一个窗口让你分享和关注,这个是怎么实现的呢?今天就给大家讲解下如何在微信公众平台前端网页上添加分享 ...

  7. python-面向对象-内置方法补充

    __del__item系列 __getitem__ __setitem__ __delitem____hash____eq__ 构造方法 申请一个空间析构方法 释放一个空间之前执行某对象借用了操作系统 ...

  8. jsp内置的对象【jsp可用数据容器】

    jsp的内置对象用法:可以存放数据进去,本身页面可以调用,发生页面请求时,请求目标可以调用 理解:jsp就是一个大容器,有请求,响应等内置对象,会话需要从请求容器中提取 请求中内置session,发出 ...

  9. Jsp内置对象和EL隐藏(内置)对象

      JSP中的内置对象一共有九个, 由于有的不太常用, 所以总是记不住, 从Sun公司的网站上找到的PDF文档, 把这一部分放在这里, 以备随时查用:     JSP九个内置对象: Implicit ...

随机推荐

  1. 第一章 Hyper-V 2012 R2角色部署

      在windows server 2012 R2中,我们可以通过安装hyper-v角色来完成虚拟化底层架构的部署.除了图形界面的安装,也可以使用单独的发行版Hyper-V Server 2012 R ...

  2. nginx基础知识总结

    1.nginx的工作模式 master/worker工作模式: 一个master进程: 负载加载和分析配置文件.管理worker进程.平滑重启升级等. 一个或多个worker进程 处理并响应用户请求 ...

  3. iOS-省市区选择的实现

    一.简介 该文主要实现的是省市区的选择,可在个人修改地址的地方使用. 二.需要的东西 制作这个首先需要一个area.plist文件,该文件中保存这所有的关于省市区的信息,下载地址:http://pan ...

  4. vue_表单控件

    Vue.js中提供 v-model 的指令对表单元素进行双向数据绑定,在修改表单元素值的同时,实例 vm 中对应的属性值也同时更新,反之亦然.本小节介绍主要input元素绑定v-model 后的具体用 ...

  5. 网络流(四)dinic算法

    传送门: 网络流(一)基础知识篇 网络流(二)最大流的增广路算法 网络流(三)最大流最小割定理 网络流(四)dinic算法 网络流(五)有上下限的最大流 网络流(六)最小费用最大流问题 转自:http ...

  6. Java程序在Linux上运行虚拟内存耗用很大

    突然集群的2个节点挂了,通过top查看, 虚拟内存22G, 通过 pmap -x 8 | grep anon 一大堆64M Linux下glibc的内存管理机制用了一个很奇妙的东西,叫arena.在g ...

  7. leetcode 20. Valid Parentheses 、32. Longest Valid Parentheses 、

    20. Valid Parentheses 错误解法: "[])"就会报错,没考虑到出现')'.']'.'}'时,stack为空的情况,这种情况也无法匹配 class Soluti ...

  8. yum问题解决

    错误信息1:There was a problem importing one of the Python modulesrequired to run yum. The error leading ...

  9. 使用 Apache Web 配置多个站点

    导读 如何在流行而强大的 Apache Web 服务器上托管两个或多个站点.这篇文章的环境是 Fedora 27 虚拟机,配置了 Apache 2.4.29.如果你用另一个发行版或不同的 Fedora ...

  10. 20175310 《Java程序设计》第2周学习总结

    20175310<Java程序设计>第2周学习总结 教材学习内容总结 本周学习了第二章和第三章的内容,大部分的知识点都和大一学的C语言很相似,学起来难度不大. 教材学习中的问题和解决过程 ...