练习题
A = {n: 4399}; //声明一个A对象,成员n为4399
var B = function() {
this.n = 9999
} //声明一个B函数,谁调用这个函数创建新对象,则创建属性n为9999
var C = function() {
var n = 8888
} //声明一个C函数,定义一个n为8888
B.prototype = A;
C.prototype = A; //将B,C函数的prototype属性改变为A对象
var b = new B(); //b{__proto__:{A},n:9999}
var c = new C(); //c{__proto__:{A}}
A.n++; //A = {n: 4400};
console.log(b.n); //9999
console.log(c.n); //c对象中没有n,所以就去原型对象中找 所以为4400
离它最近的function这个函数是谁代用的 this就是谁 没有function就是window
this new prototype __proto__
this==>离它最近的function这个函数是谁代用的 this就是谁 没有function就是window
fn()==>window
obj.say()==>obj
xx1.xx2[10].xx3()==>数组中第11个数据 xx1.xx2[10]
(obj.say)()==>obj
(obj1.say=obj2.say)==>window
fn()()===>window
当我们要new一个函数的时候,有三步步骤
new fn()
1.创建一个空对象,把这个对象的__proto__赋值为fn.prototype==>{_proto:fn.prototype}
2.执行fn函数 fn函数内部的this代表创建出来的这个对象
3.fn函数的返回值是基本数据:表达结果就是创建的对象 引用数据的话,表达式结果就是fn的返回值
prototype 和____proto的差别
1.任何引用数据(对象)都有原型对象==>都有__proto__属性
2.任何函数都能够创建对象==>任何函数都有prototype属性
3.函数创建出来的对象 的原型对象不是这个函数对象==>obj.__proto__不是fn函数也不是fn.__proto它是fn.prototype
当我们获取一个对象的数据的时候,会有如下2个过程:
obj.xx==>
1.如果对象自己没有xx 就会去原型上访问,原型没有就去原型的原型上访问
2.直到null没有返回undefined 这个就是原型链
这个一步步往原型的原型上面走的过程,就是我们顺着原型链一直往上爬,最顶点就是null,如果到了最顶点null都没找到这个需要访问的值,那说明就是没有在全局中进行定义了
当我们想初始化一个对象中的数据时
obj.xx=[]
不管原型链上没有xx这个成员 都会给自己添加xx这个成员
obj.xx.操作==>真的会操作原型(做项目基本没有,题)
只修改整个属性只会给自己这一层添加或者赋新值,如果不是修改整个成员,而是该成员内部操作,就会操作原型对象
eg:
obj.__proto__.name1="wangchuan" //在__proto__成员中添加一个name1属性,赋值为"wangchuan"
obj.__proto__="{name:wangchuan}" //把整个obj.__proto成员所存的原来的原型对象的地址替换成{name:wangchuan}对象的地址
方法劫持
方法劫持
call apply 使用方法差不多,只有小差别
bind 差距较大
var obj1={name:"jack",age:18,say:function (arg1,arg2) {
console.log(arg1,arg2)
console.log(this.name,this.age)
}}
var obj2={name:"xxxxx",age:"xxxx"}
obj1.say() //jack,18
obj2.xxx=obj1.say
obj2.xxx() //xxxxx,xxxx
obj1.say.call(obj2,100,200) //.call前面就是正常读,使用obj1的say方法,但是使用的对象为括号里的第一个参数,也就是obj2,达到劫持的效果,使用劫持后,say方法的this全部为obj2,后面的参数为传进去的实参100和200
function fn (arg1) {
console.log(this)
console.log(arg1)
}
fn.call(obj1,"hello") //直接通过函数来劫持也可以,不一定非要使用对象中的方法进行劫持
fn.apply(obj2,[100])
obj1.say.apply(obj2,[100,200]) //apply和call的不同在于传进去的实参,call是通过逗号,连接,并以此传入,apply是通过将数据传入数组,然后将这个数组给函数中的argument达到赋值的效果
call apply 函数调用的时候为函数内部指定this对象
bind 方法在设计的时候就为其指定this对象,以后都不能被修改
var obj1={name:"jack"};
var obj2={name:'karen',say:function() {
console.log(this)
}.bind(obj1)}
obj2.say()
obj2.say.call(window)
obj2.say.apply(window); //打印出来都是obj1
因为在定义的时候就绑定了bind,以后无论如何只要这个函数进行使用,那么他的使用对象就是obj1
声明的函数不能直接绑定 只能方法直接绑定(声明式的不能直接绑定,定义式的可以直接绑定 )
意思就是,如果我通过直接写一个方法出来加bind方法不行,但是如果我是在一个对象中,写方法的时候在方法后面加bind就可以
obj1.say1=function() {
console.log(this)
}.bind(obj2) //这样写是可以的
obj1.say1.bind(obj2) //这样是不行的
var str="hello"
var re=str.charAt(1)
console.log(re) //e
将这个字符串每一个字符放入一个数组中,取下标为1的元素,题中为e