阮一峰JavaScript教程:面向对象编程javascript
阮一峰JavaScript教程:实例对象与 new 命令html
也能够看看这篇文章周大侠啊 进击的 JavaScript(六) 之 this先了解一下`this的四种绑定规则和箭头函数的this绑定git
这两篇文章写的很好
周大侠啊 进击的 JavaScript(六) 之 thisgithub
苏云的博客编程
下面的this分别是什么?这几个函数都是回调函数,回调函数this比较特殊,一般是事件原对象segmentfault
//1. button1.onclick = function () { console.log(this) } //2. button2.addEventListener("click", function () { console.log(this) }) //3.jQuery中 $("ul").on("click", "li", function () { console.log(this) })
this是函数.call()
的第一个参数.app
那么在直接调用函数的时候(隐式绑定,没用call),如何知道call()
的第一个参数?
源码看不到,那就看文档.框架
看文档!:
onclick:
addEventListener:
jQuery中:函数
因此上面三个的this分别是
btutton1元素,button2元素,li元素
$("ul").on("click", "li"/*selector*/, function () { console.log(this)//表明与selector相匹配的元素(li元素) })
this
是call()
的第一个参数,只有写onclick
,写addEventListener
和写jQuery
中on
的人想call()哪一个东西,就把这个this
绑定到哪里去了,因此要肯定this
,就要看源码或者文档!
例如:
button1.onclick = function () { console.log(this) } button1.onclick.call({name:"mataotao"})
能够直接触发onclick事件,传入{name:"mataotao"}
,那么this
就是{name:"mataotao"}
这个对象
如下来自苏云的博客()
6.回调函数的
this
回调函数也只不过是函数的一种,实际上这种状况已经包含在了前面提到的状况中。可是因为回调函数的调用者每每不是咱们本身,而是回调函数的接收者,即某个库或框架、甚至是JS运行时环境。这样一来,回调函数在中的this
是什么就与对方的调用方式有关了,所以变得比较复杂,因此单独拿出来讨论一下。状况1:没有明确做用对象的状况下,一般
this
为全局对象例如
setTimeout
函数的回调函数,它的this
就是全局对象。你若是但愿本身指定this
,能够经过bind
函数等方法。状况2:某个事件的监听器回调函数,一般this就是事件源对象
例如:
button.addEventListener('click', fn)
fn
的中的this
就是事件源button
对象。状况3:某些API会专门提供一个参数,用来指定回调函数中的
this
例如,咱们能够从新设计一个能够指定
this
的setTimeout
:function setTimeoutExt(cb, period, thisArg) { setTimeout(function() { cb.call(thisArg); }, period); }另外,在ExtJS中也大量使用了能够指定this的接口。
答案:
调用B处的console.log().结果是options
window(console.log()中console是全局window对象里的一个方法)
我终于明白了原型链:
仔细看下面这篇文章,就能明白原型链的构造问题:
JavaScript 世界万物诞生记
我的理解:
原型链要分为两个部分,原型和链,原型就是一个实例对象,可是是最基础的实例对象.这个实例对象能够做为模板/类,让其余对象去复制他,复制以后不仅仅有这个原型的属性,也能够有本身的属性.新实现的实例对象.__proto__
指向原来的模板实例对象.
而造出来的对象也能够当作模板,再由新的机器去以他为模板造新对象.由此造成了一条__proto__
组成的链.
全部的对象都有__proto__
属性,他们就像被链子链接在了一块儿,因此就称之为原型链
而复制的过程由一个机器来完成.这个机器(好比能够说是Object())的使用方法就是:按照模板实例对象new()一个新对象,新对象被原来的模板对象用__proto__
链子拴着,新对象能够有本身的新添加的东西.
这个按照模板造新对象的机器.prototype
指向原来的模板实例对象.prototype
就是原来的模板实例对象拴住复制本身机器的链子.
写成代码就是:
var obj = new Object({ flag: 10 });
就像前面所说,机器用来制造某一类对象。正因如此,机器能够做为这类对象的标志,即面向对象语言中 类(class)的概念。因此机器又被称为 构造函数。在ES6引入 class关键字以前,咱们经常把构造函数叫作类。说明2:用户自定义的函数一般既能够做为普通函数使用,又能够做为构造函数来制造对象。ES6新增的class语法定义的函数只能做为构造函数,ES6新增的=>语法定义的箭头函数只能做为普通函数。
.
__proto__
与prototype
的区别__proto__
是全部对象(包括函数对象)都有的一个属性(固然只是逻辑上有这么个概念),当咱们说“原型链”的时候,就是指 对象经过这个属性互相链接而造成的链状结构。 原型链也就是 继承链。
prototype
是只有函数(准确地说是 构造函数)才有的一个属性,例如对于对于某个函数Fun。它的意义在于,当你用var obj = new
Fun() 获得一个对象obj时,这个obj的原型就是F.prototype。即(new Fun()).__proto__ ===Fun.prototype
,见文中第4个图。No. 1其实就是
Object.prototype
,No.
2其实就是Function.prototype。我只是为了强调这两个对象的重要性,故意这样说的。不太严格地说,前者就是一个空对象相似:{}
,后者就是一个空函数,相似:fubction() {} 。
文中:
**No. 1:Object.prototype
No. 2:Function.prototype**
还有这几篇文章也不错:
「每日一题」什么是 JS 原型链? - 方应杭的文章 - 知
看看这篇文章很清楚:
JS 的 new 究竟是干什么的? - 方应杭的文章 - 知乎
以共有属性对象为模板new出来的新对象的__proto__指向共有属性对象(我把这个对象叫作模板对象,也叫做原型).这样共有属性在内存中只须要存一次!
好比:当咱们造士兵的时候,士兵有共有属性,有自有属性,那么咱们能够把共有属性放在一个地方,避免每一次建立士兵都把共有属性从新建立一次,浪费内存:
既然这样,那么咱们能够把制造士兵的过程写成一个函数.
而后调用便可
直接使用函数就能够制造一个有特殊的id,可是__proto__
指向原型士兵的新士兵
那么可不能够直接把这个原型对象放到函数里,组成一个总体?不行,这样每次调用这个函数,都会在内存中建立这个临时对象,那么和原先的不用原型同样了
解决方法是,把这个原型变为函数的一个属性
这种方法省内存且好用.
new()就是刚刚的全部过程
灰色的代码就是new()作的封装,不须要你作的事情
共有属性被new()统一叫作prototype
new其实就是语法糖!
注意:.prototype
对象最开始就是一个拥有constructor
属性的对象,若是想修改共有属性,两种方法:
第一步写私有属性,第二步写共有属性.
能够看到这个对象的
1自有属性,
2__proto__指向的原型对象含有共有属性.
3constructor指向的构造函数
也能够看看这篇文章周大侠啊 进击的 JavaScript(六) 之 this
里面有new的实现.new与this
下面是节选:
5、new 绑定 若是 使用
new
来建立对象,由于
后面跟着的是构造函数,因此称它为构造器调用。对于this
绑定来讲,称为new
绑定。想知道 构造器调用 中
this
的绑定,就要知道new
到底作了啥了。先来个
new
的实现。看不懂没关系,在后面原型链那篇,还会说的。function New(proto){ //proto 为传进来的构造函数 var obj = {}; obj.__proto__ = proto.prototype; proto.apply(obj, Array.prototype.slice.call(argument,1)); //你这要看懂这步就行。这里把构造函数里的 this 绑定到了 新的obj 对象上,最后 返回了该新对象,做为实例对象。 return obj; }因此在使用
new
来建立实例对象时,new
内部把 构造函数的this
绑定到 返回的新对象 上了。function Person(name){ this.name = name; } var c = new Person("zdx"); c.name;
JavaScript 世界万物诞生记中也提到了new的使用,new的过程就是生产机器按照模板原型对象造出来的新对象的过程!