apply、call 、bind 作用&区别
<pre>
//语法
apply:| fun.apply(thisArg, [argsArray])
call:| fun.call(thisArg[, arg1[, arg2[, ...]]])
bind:| fun.bind(thisArg[, arg1[, arg2[, ...]]])
</pre>
-
apply
&call
的作用:>本质都是改变函数的执行环境上下文,即this指向。区别:>是apply的参数是传入数组或类数组,而call的参数是若干个指定参数。
<pre>
var hobby = 'sleep'
var 小强 = { hobby: 'play' }
var 小明 = { hobby : 'eat' }
function yourhobby(){ console.log(this.hobby) }
yourhobby() // >sleep< this指向window yourhobby.call(小强) // >play< this指向小强 yourhobby.apply(小明) // >eat< this指向小明
</pre>
<pre>
var _array = [6, 2, 2, 6, 9, 3, 2, 9, 0] Math.min.apply(null,_array) // >0< 可直接处理数组 Math.max.call(null,6, 2, 2, 6, 9, 3, 2, 9, 0) // >9< 需要一一键出
</pre>
bind()
方法创建一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。
<pre>
this.x = 9; var module = { x: 81, getX: function() { return this.x; } };
module.getX(); // 返回 81
var retrieveX = module.getX; retrieveX(); // 返回 9, 在这种情况下,"this"指向全局作用域
// 创建一个新函数,将"this"绑定到module对象 // 新手可能会被全局的x变量和module里的属性x所迷惑 var boundGetX = retrieveX.bind(module); boundGetX(); // 返回 81
</pre>
以下代码输出什么?
<pre>
var john = { firstName: "John" } function func() { alert(this.firstName + ": hi!") } john.sayHi = func // 为john 增一sayHi属性,并赋其func方法 john.sayHi() // John hi!
</pre>
下面代码输出什么,为什么
<pre>
func() function func() { alert(this) // [object Window] }
//因为this指向 window 所以打印出 window 对象
</pre>
下面代码输出什么
<pre>
document.addEventListener('click', function(e){ console.log(this); // 指向/打印 文档 setTimeout(function(){ console.log(this); // 指向/打印 window }, 200); }, false);
//由setTimeout()调用的代码运行在与所在函数完全分离的执行环境上. //这会导致,这些代码中包含的 this 关键字会指向 window (或全局)对象, //这和所期望的this的值是不一样的
</pre>
下面代码输出什么,why
<pre>
var john = { firstName: "John" } function func() { alert( this.firstName ) } func.call(john) // 打印 > John
// call 使this指向 john 对象..
</pre>
以下代码有什么问题,如何修改
<pre>
`var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) // this指向eventTarget,在此即被点击的DOM元素($btn)
this.showMsg(); // this 指向的 Dom 元素 无此函数0.0无法运行
})
},
showMsg: function(){
console.log('checked~');
}
}</pre><pre>
var module= {
bind: function(){
var _this = this // 把this保存起来
$btn.on('click', function(){
console.log(this) // > $btn Dom按钮
_this.showMsg(); // 触发下面方法
})
},
showMsg: function(){
console.log('checked~~~');
}
}`
</pre>
原型链相关问题
有如下代码,解释Person、 prototype、proto、p、constructor之间的关联。
<pre>
function Person(name){ this.name = name; } Person.prototype.sayName = function(){ console.log('My name is :' + this.name); } var p = new Person("小明") p.sayName(); // Analyze... console.dir( rel = [ Person.prototype.constructor == Person, Person.prototype == p.__proto__, p.__proto__.constructor == Person, Person.prototype.__proto__ == Object.prototype, Object.prototype.constructor == Object, Object.prototype.__proto__ == null ] );
</pre>
上例中,对对象 p可以这样调用 p.toString()。toString是哪里来的? 画出原型图?并解释什么是原型链。
p
本身无此方法..该方法是因构造函数的 __proto__
指向对象原型.所以从对象原型中继承而来。
使用一个构造函数创造一个实例对象,在此对象上调用相应的属性和方法时,首先查找它本身有没有,如果没有,则顺着proto这个指针去找它的构造函数的原型上有没有,如果没有,再顺着原型的proto向上去找,也就是说,只要存在proto这个指针,在没有找到对应的属性与方法时,查找不会停下,直到没有proto为止,这样的一种形式可行的结构基础就叫原型链。
对String做扩展,实现如下方式获取字符串中频率最高的字符
<pre>
//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 = 'adbabisbvibibqdasxcz'; var ch = str.getMostOften() console.log(ch) </script>
//结果返回: Object maxKey:"b" maxNum:5
</pre>
instanceof有什么作用?内部逻辑是如何实现的?
instanceof
运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。
语法:object instanceof constructor
<pre>
function _instanceof(obj,fn) { var nextobj = obj.__proto__ do { if(nextobj === fn.prototype) { return true; } else { nextobj = nextobj.__proto__; } }while(nextobj) return false; }
</pre>
继承相关问题
继承有什么作用?
抽象事物从一般到特殊的过程,使得更具体的事物共享那些更通用的属性与方法,减少重复,通常我们将更具体的事物称为子类,把抽象的事物称为父类。我们可以灵活的给子类添加特定的属性与方法以此来使其拓展父类的功能,而又不影响父类本身。
下面两种写法有什么区别?
<pre>
`//方法1
function People(name, sex){
this.name = name;
this.sex = sex;
this.printName = function(){ //通用的这一步放于此会减低复用性
console.log(this.name);
}
}
var p1 = new People('小强', 18)
//方法2
function Person(name, sex){
this.name = name;
this.sex = sex;
}
Person.prototype.printName = function(){ // 把通用方法放于原型链中,增加复用性。
console.log(this.name);
}
var p1 = new Person('小明', 100);`
</pre>
Object.create 有什么作用?兼容性如何?
Object.create() 方法使用指定的原型对象和其属性创建了一个新的对象。
语法: Object.create(proto, [ propertiesObject ])
hasOwnProperty有什么作用? 如何使用?
hasOwnProperty() 方法会返回一个布尔值,指示对象是否具有指定的属性作为自身(不继承)属性。
语法: obj.hasOwnProperty(prop=要检测的值)
<pre>
o = new Object(); o.prop = 'exists'; o.hasOwnProperty('prop'); // 返回 true o.hasOwnProperty('toString'); // 返回 false o.hasOwnProperty('hasOwnProperty'); // 返回 false
</pre>
如下代码中call的作用是什么?
<pre>
function Person(name, sex){ this.name = name; this.sex = sex; } function Male(name, sex, age){ Person.call(this, name, sex); // Male下执行Person,call 使Person构造函数在此作用域下能够访问并继承 Person 的属性. this.age = age; }
</pre>
补全代码,实现继承
<pre>
`function Person(name, sex){
// todo ...
this.name = name;
this.sex = sex;
}
Person.prototype.getName = function(){
// todo ...
console.log('My name is ' + this.name)
};
function Male(name, sex, age){
//todo ...
Person.call(this, name, sex)
this.age = age;
}
Male.prototype = Object.create(Person.prototype);
Object.create(Person.prototype).construtor = Male
//todo ...
Male.prototype.getAge = function(){
console.log(this.name);
};
var xiaom = new Male('小明', '男', 18);
xiaom.getName();`
</pre>