typora-copy-images-to: media
第02阶段.前端基本功.前端基础.js进阶
重新认识instanceof
- 原型链不可变
- for..in的问题
重点
重点
上下文调用模式
js中的继承
闭包
?
js基础阶段对instanceof作用的描述 : 判断一个对象是否是某个构造函数的实例
现在我们学习了原型,也学习了原型链,所以我们现在可以更严谨的描述他的作用:
判断一个函数的原型对象,是否在实例对象的原型链上
var arr = [];
console.log(arr instanceof Array); //true
console.log(arr instanceof Object); //true
function Person(){
}
var p1 = new Person();
console.log(p1 instanceof Person); // ?
Person.prototype = {
constructor : Person,
a : 1
}
console.log(p1 instanceof Person); // ?
var p2 = new Person();
console.log(p2 instanceof Person); // ?
普通调用
this -- > window
function fn(){
console.log(this); // window
}
fn();
对象调用
this -- > obj
function fn(){
console.log(this) // obj
}
var obj = {
f : fn
};
obj.f();
构造函数调用
this -- > 构造函数的实例
function Person(name){
this.name = name; //this --> 实例
}
var p1 = new Person('zs');
定时器中的回调函数
this -- > window
setTimeout(function(){
console.log(this)// window
},1000);
事件处理函数调用
this --> 事件源
box.onclick = function(){
console.log(this); // box
}
?
我们总结了一句话: this的指向是在函数调用时决定的. 谁调用这个函数,this指向谁
为什么要学习上下文调用函数?
因为这样我们就可以随意的控制函数中this的指向
作用: 调用该函数,并修改函数中this的指向
语法: 函数名. call(对象,[实参]);
参数详解:
第一个参数: 要让函数中this指向谁,就写谁
后面的参数: 被调用函数要传入的实参,以逗号分隔
function fn(x, y){
console.log(this); // ['a','b','c']
console.log(x + y); //8
}
fn.call(['a','b','c'], 3, 5);
作用: 调用该函数,并修改函数中this的指向
语法: 函数名. apply(对象,数组);
参数详解:
第一个参数: 要让函数中this指向谁,就写谁
第二个参数: 要去传入一个数组,里面存放被调用函数需要的实参
function fn(x, y){
console.log(this); // {a : 1}
console.log(x + y); //8
}
fn.apply({a : 1}, [3, 5]);
作用: 不调用函数,克隆一个新的函数,并修改新函数中this的指向,将新的函数返回
语法: 函数名. bind(对象[,实参]);
参数详解:
第一个参数: 要让函数中this指向谁,就写谁
后面的参数: 被调用函数要传入的实参,以逗号分隔
function fn(x, y){
//调用newFn时打印结果
console.log(this); //{b:2}
console.log(x + y); //8
}
var newFn = fn.bind({b:2}, 3, 5);
newFn();
for...in 遍历时,会把原型上的属性也遍历出来
function Person(name){
this.name = name;
}
Person.prototype.type = 'human';
var zs = new Person('zs');
for(var key in zs){
console.log(key); // name , type 把type也打印出来了
}
如果我们就想打印对象自己身上的属性,可以使用hasOwnProperty方法来解决
hasOwnProperty的作用: 判断是不是对象自己的属性
hasOwnProperty的语法: 对象.hasOwnProperty(‘属性‘) 是则返回true, 否则false
function Person(name){
this.name = name;
}
Person.prototype.type = 'human';
var zs = new Person('zs');
for(var key in zs){
if(zs.hasOwnProperty(key)){
console.log(key); //只有自己的name
}
}
此时我们希望son对象,也拥有far对象的money, house这些属性,但是我们不想再重新写一遍,怎么办?
var far = {
money : $1000000000,
house : ['别墅', '大别墅', '有游泳池的打别墅', '城堡'];
}
var son = {
}
var far = {
wife : '小龙女',
money : 1000000000,
house : ['别墅', '大别墅', '有游泳池的打别墅', '城堡']
}
var son = {
wife : '小黄飞',
}
//通过for..in遍历far
for(var key in far){
son[key] = far[key];
}
console.log(son); // 此时son拥有了money和house .
但是以上代码书写存在一个问题 : 把wife的值也继承下来了.我们希望自己有的,就不继承了.所以我们要改一下代码
for(var key in far){
//自己没有的才继承
if(!son.hasOwnProperty(key)){
son[key] = far[key];
}
}
这样处理解决刚才的问题,但是我们发现两个对象上面存在一样的代码.这样比较占用内存
通过ceate方法实现继承,可以避免遍历对象方式,占用内存的问题
create方法语法: Object.create(参考对象) 返回一个新的对象
create方法的作用: 返回的新的对象的__proto__
指向参考对象
var far = {
wife : '小龙女',
money : 1000000000,
house : ['别墅', '大别墅', '有游泳池的打别墅', '城堡']
}
var son = Object.create(far);
son.wife = '小黄飞';
console.log(son.money); //1000000000
console.log(son.house); //['别墅', '大别墅', '有游泳池的打别墅', '城堡']
console.log(son.wife); // 小黄飞
console.log(son.__proto__ === far); //true
我们工作中要经常创建多个具有相同属性的对象,所以经常要写构造函数.
那么构造函数创建的出来的对象该如何实现继承呢?
function Person(name, age){
this.name = name;
this.age = age;
this.sayHello = function(){
console.log('hello, ' + '我是' + this.name );
}
}
function Student(name, age, score){
this.score = score;
Person.call(this, name, age);//借用构造函数
}
var stu = new Student('zs', 18, 100);
console.log(stu); //{score : 100, name : zs, age : 18}
stu.sayHello(); //hello, 我是zs
但是我们一般不会把方法写在构造函数的函数体内,我们把方法写在函数的原型上,那么这个时候构造借用函数就无法继承方法了,我们想要继承原型上的方法.可以用原型继承
用来继承方法
function Person(name, age){
this.name = name;
this.age = age;
this.sayHello = function(){
console.log('hello, ' + '我是' + this.name );
}
}
function Student(name, age, score){
this.score = score;
}
Student.prototype = new Person();
var stu = new Student('zs', 18, 100);
console.log(stu); //{score : 100}
stu.sayHello(); //hello, 我是undefined
我们发现,方法继承下来了,但是属性却没有继承下来
借用构造函数 + 原型继承
function Person(name, age){
this.name = name;
this.age = age;
this.sayHello = function(){
console.log('hello, ' + '我是' + this.name );
}
}
function Student(name, age, score){
this.score = score;
Person.call(this, name, age);
}
Student.prototype = new Person();
var stu = new Student('zs', 18, 100);
console.log(stu); //{score : 100, name : zs, age : 18}
stu.sayHello(); //hello, 我是zs
概念: 函数和函数作用域的结合
通俗理解: 内部函数使用外部函数的变量, 整个外部函数形成了一个闭包
function main(){
var money = 10000; //放到局部作用中,防止全局变量污染(私有化数据)
return {
queryMoney : function(){
return money;
},
payMoney : function(num){
money -= num;
},
addMoney : function(num){
money += num;
}
}
}
var moneyManger = main(); // 通过moneyManger 可以获取到局部的变量money
由于内部的函数使用了外部函数的变量,导致外部这个函数无法被回收掉.如果代码中大量的存在闭包,可能会导致内存泄露 (不要刻意使用闭包);
成员: 泛指属性和方法
静态成员: 函数也是对象, 函数自己的属性
实例成员: 特指构造函数时,写在构造函数体内,通过this.xxx.给实例添加的属性
function Person(){
this.name = name; //实例成员
this.age = age; // 实例成员
}
Person.type = '呵呵'; //静态成员
Functon 自己创造了自己
Object是Function的实例
原文:https://www.cnblogs.com/f2ehe/p/11922121.html