console.log(this)
//window
var a = 1
//全局变量 相当于window的属性
window.a
//1
this.a
//1
var a = 1
var b = 100
console.log(this) //window
function fn1(){
console.log(a)
console.log(this) //window
var b = 2
console.log(this.b); //100
}
fn1()
setTimeout setInterval
这两个方法执行的函数this也是全局对象
document.addEventListener('click', function(e){
console.log(this);
setTimeout(function(){
console.log(this); //window
}, 200)
}, false);
保存起来
//var _this = this;
//var me = this;
//var self = this;
document.addEventListener('click', function(e){
console.log(this);
var _this = this;
setTimeout(function(){
console.log(_this);
}, 200);
})
作为构造函数调用
所谓构造函数 就是通过这个函数生成一个新对象(object)
这时 this就指这个新对象
new运算符接受一个函数F及其参数 new F(arguments...) 这一过程分三步
1.创建类的实例 这步是把一个空的对象的 __proto__属性设置为
F.prototype
2.初始化实例 函数F被传入参数并调用 关键字this被设定为该实例
3.返回实例
function Person(name){
this.name = name;
}
Person.prototype.printName = function(){
console.log(this.name)
}
var p1 = new Person('Byron')
var p2 = new Person('Casper')
var p3 = new Person('Vincent')
p1.printName();
p2.printName();
p3.printName();
作为对象方法调用
在js中 函数也是对象 因此函数可以作为一个对象的属性 此时该函数被
称为该对象的方法 在使用这种调用方法时 this被自然绑定到该对象上
var obj1 = {
name: 'Byron',
fn: function(){
console.log(this);
}
}
obj1.fn() //Object {name: 'Byron'}
var obj2 = {
name: 'Byron',
obj3: {
fn: function(){
console.log(this)
}
}
}
obj2.obj3.fn() //Object -----指向fn
var fn2 = obj1.fn
fn2() //window
「读」属性时会沿着原型链搜索。
「新增」属性时不会去看原型链(但是如果你给这个属性加了一些配置,则不一样)。
比如求数组中最大值
var arr = [1,2,7,4]
//Max.max(1,2,7,4)
console.log( Math.max.apply(null, arr) )
再比如
function joinStr(){
console.log( Array.prototype.join.call(arguments, '-') )
//或者
var join = Array.prototype.join.bind(arguments)
console.log(join('-'))
}
joinStr('a', 'b', 'c')
三种变量
实例变量: (this)类的实例产能访问到的变量
静态变量: (属性)直接类型对象能访问到的变量
私有变量: (局部变量) 当前作用域类有效的变量
继承
继承指一个对象直接使用另一个对象的属性和方法
function Person(name, age){
this.name = name
this.age = age
}
Person.prototype.sayName = function(){
console.log('My name is ' + this.name)
}
Person.prototype.walk = function(){
console.log(this.name + 'is walking')
}
var p = new Person('ruoyu', 100)
function Student(name, age, sex){
Person.bind(this)(name, age)
this.sex = sex
}
Student.prototype = Object.create(Person.prototype)
Student.prototype.constructor = Student
Student.prototype.doing = function(){
console.log('I am studing')
}
var s = new Student('hunger', 2, 'boy')
s
//Student.prototype.__proto__ = Person.prototype
function People(name){
this.name = name;
this.sayName = function(){
console.log(this.name)
}
}
People.prototype
//Object {}
People.prototype.a = 1
//1
People.prototype
//Object {a: 1}
p = new People()
p.__proto__
//Object{}
this相关问题
题目1:apply、call 、bind有什么作用,什么区别
Function.prototype.bind
bind 任何函数都有bind方法
bind 返回一个新函数,并且使得函数内部的this
为传入的第一个参数
var fn3 = obj1.fn.bind(obj1);
fn3
document.addEventListener('click', function(e){
console.log(this); //#document
setTimeout(function(){
console.log(this); //#document
}.bind(this), 200);
}, false);
call apply 调用一个函数,传入函数执行上下文及参数
fn.call(context, param1, param2...)
fn.apply(context, paramArray)
call与apply功能完全一样,参数的用法不一样
var value = 100
var obj = {
value: 200
}
function fn4(a, b){
console.log(this.value + a + b)
}
fn4(3, 4) //107
fn4.call(obj4, 3, 4) //207
fn4.apply(obj4, [3, 4]) //207
题目2:以下代码输出什么?
2.png//为 john对象新增一个属性sayHi
//结果为
//"John: hi!"
题目3:下面代码输出什么,为什么
3.png//结果为
//[object window]
//此时this指向window 所以打印出window对象
题目4:下面代码输出什么
4.png//结果为
#document
Window{...}
//第一个 为dom元素绑定事件 所以this指向#document
//而setTimeout指向window
题目5:下面代码输出什么
5.png弹窗 John
//call 使this指向john对象
题目6:以下代码有什么问题?如何修改
6.pngconsole.log(this) //这个this指的是$btn
this.showMsg() //不能运行 $btn中没有这个方法
//改进
var module = {
bind: function(){
var _this = this
$btn.on('click', function(){
console.log(this)
_this.showMsg()
})
},
showMsg: function(){
console.log('checked');
}
}
原型链相关问题
题目7:有如下代码 解释Person prototype proto p constructor之间的关联
7.pngPerson.prototype.constructor === Person
Person.prototype === p.__proto__
p.__proto__.constructor === Person
Person.prototype.__proto__ === Object.prototype
题目8:上例中,对对象p可以这样调用p.toString() toString是哪里来的?画出原型图?并解释什么是原型链
p本身没有这个方法
p从原型中继承得到toString()方法
因为任何类的prototype属性本质上都是个类Object的实例,所以prototype也和其它实例一样也有个__proto__内部属性,指向其类型Object的prototype
我们大概可以知道为什么了,自己的类的prototype找不到的话,还会找prototype的类型的prototype属性,这样层层向上查找
大概过程是这样的
记当前对象为obj,查找obj属性、方法,找到后返回
没有找到,通过obj的__proto__属性,找到其类型Array的prototype属性(记为prop)继续查找,找到后返回
没有找到,把prop记为obj做递归重复步骤一,通过类似方法找到prop的类型Object的 prototype进行查找,找到返回
题目9:对String做扩展,实现如下方式获取字符串中频率最高的字符
9.png//var str = 'ahbbccdeddddfg';
//var ch = str.getMostOften();
//console.log(ch); //d , 因为d 出现了5次
<script>
String.prototype.getMostOften = function(){
var _this = this
var obj = {}
for(var i=0; i<_this.length; i++){//循环这个字符串
if(obj[_this[i]]){
obj[_this[i]]++
} else {
obj[_this[i]] = 1
}
}
var maxNum = 0,
maxKey
for (var key in obj) {
if(obj[key] > maxNum) {
maxNum = obj[key]
maxKey = key
}
}
return {
maxKey,
maxNum
}
}
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften()
console.log(ch)
</script>
题目10:instanceof有什么作用?内部逻辑是如何实现的?
instanceof用来检测一个对象在其原型链中是否存在一个构造函数的
prototype属性
object instanceof constructor
function _instanceof(obj,fn) {
var nextobj = obj.__proto__
do {
if(nextobj === fn.prototype) {
return true;
} else {
nextobj = nextobj.__proto__;
}
}while(nextobj)
return false;
}
继承相关问题
题目11:继承有什么作用?
减少重复,使得一个对象可以直接使用另一个对象的属性和方法
题目12:下面两种写法有什么区别
12.png方法2将 方法放在原型链上,可以增加复用性
题目13:Object.create有什么作用?兼容性如何?
Object.create(proto[, propertiesObject])
Object.create() 方法会使用指定的原型对象及其属性去创建一个新的对象
兼容性.png
题目14:hasOwnProperty有什么作用?如何使用?
hasOwnProperty是Object.prototype的一个方法,可以判断一个对象是否包含
自定义属性而不是原型链上的属性
hasOwnProperty是JavaScript中唯一一个处理属性但是不查找原型链的函数
o = new Object();
o.prop = 'has';
o.hasOwnProperty('prop') //true
o.hasOwnProperty('toString') //false
o.hasOwnProperty('hasOwnProperty') //false
题目15:如下代码中call的作用是什么?
15.png使得Person函数在此作用域下能够被访问和继承
题目16:补全代码,实现继承
16.pngfunction Person(name, sex){
this.name = name
this.sex = sex
}
Person.prototype.getName = function(){
console.log('My name is ' + this.name)
}
function Male(name, sex, age){
Person.call(this, name, sex);
this.age = age;
}
Male.prototype = Object.create(Person.prototype);
Male.prototype.getAge = function(){
console.log(this.age);
}
var ruoyu = new Male('若愚', '男', '28')
ruoyu.getName();
网友评论