HTML5前端for循环结果的指向学习分享
这是在写Ajax项目里的购物车数量的更改时到的:
在下面的例子里,触发事件后a指的是循环的最后一个结果,而不是当前触发事件的对象所以以后在循环里写事件时不要直接声明一个循环变量来触发事件因为这样写是不准确的,即使用的是let声明的变量产生独立作用域也不行,例如:
for(let j=0;j
var a=onum[j];
a.oninput=function(){
console.log(this)
console.log(onum[j]);
}
}
准确的写法是
for(let j=0;j
onum[j].oninput=function(){
console.log(this)或者
console.log(onum[j]);
}
}
Array.from的方法测试
/*Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象,常见的类似数组的对象是 DOM 操作返回的 NodeList 集合,以及函数内部的arguments对象*/
var obj1={"a":"1","b":"2","c":"3",length:3};
console.log(Array.from(obj1));//[undefined, undefined, undefined]
var obj2={"1":"a","2":"b","3":"c",length:3};
console.log(Array.from(obj2));//[undefined, "a", "b"]
var obj3={"0":"a","1":"b","2":"c",length:3};
console.log(Array.from(obj3));//['a', 'b', 'c']
var obj4={"0":"a","1":"b","2":"c"};
console.log(Array.from(obj4));//[];
// var obj5={"0":"a","1":"b","2":"c",,length:6};
// console.log(Array.from(obj5));//长度多写或少写都会直接报错
var obj6={0:"a",1:"b",2:"c",length:3};
console.log(Array.from(obj6));//['a', 'b', 'c'];
/*通过上面六次测试可以看出想要使用Array.from方法将对象转换成数组,那么对象里的属性名要写成数组中的从0开始的下标值,属性值才是下标值所代表的元素,下标值可以不用引号裹住,还要写上长度,长度值不能写多或少,有几个属性长度值就是几,否则直接报错*/
构造函数的几种写法、继承和常犯错误
构造函数的的写法和调用一直是我头疼的问题,至今我写的大部分bug都是因为对构造函数掌握的不熟练产生的,刚开始学的时候感觉很简单,但是自己创建、调用的时候却傻眼了,可以说我创建的不是构造函数,而是大大的bug,所以第一次月考结束后我就总结了我所学到的所有es5、es6的构造函数,忘记了哪个就去看哪个,不仅容易找到,还能顺带复习一下其他的写法。
//如果调用对象里没有的属性并给这个属性赋值
//那么该属性会动态的添加到对象里
//对象里的方法也可以这样动态的添加
var obj={"name":"张三"};
obj.age=19;
console.log(obj);//age:19,name:"张三"
//第一种构造函数写法:es5
function Person(name,age){
this.name=name;
this.age=age;
console.log(this.name,this.age);
this.per=function(){
console.log("第一种写法:“=”");
}
}
var student1=new Person("学生1",18);
console.log(student1.name);
console.log(student1["name"]);
//正确的调用:当做构造函数调用
student1["per"]();//第一种写法:“=”
student1.per();//第一种写法:“=”
//正确的调用:当做普通函数调用
Person("张三",23);
//错误的输出
//console.log(student1["per"]());//undefined
//console.log(student1.per());//undefined
//第二种构造函数写法(es5):json
var json1={"name":"小明",
"age":18,
"sex":"男",
"num":5050,
"num1":123456789,
"zy":"会计",
"zwjs":function(){
console.log("第二种写法:“:”");
//在后台打印里如果输出换行会被当成字符串输出
document.write(this.name+"
"+this.age+"
"+this.sex+"
"+this.num+"
"+this.num1+"
"+this.zy)
}
};
//正确的调用
console.log(json1.name);
json1.zwjs();
//错误的调用
//console.log(json1.zwjs());
es5里的构造函数继承
function Person1(name){
this.name=name;
this.hello=function(){
console.log("我的名字是"+this.name);
}
}
function Person2(name,age){
//继承步骤:第一步自定义一个属性指向所要继承的构造函数名
this.method=Person1;
//第二步:调用这个自定义属性,也就是调用所要继承的构造函数
this.method(name);
//第三步:删除这个自定义属性,因为此时这个函数已经成功继承
//这个步骤可写可不写
delete this.method;
//这个是增加的属性
this.age=age;
this.me=function(){
console.log(name,age);
}
}
var p1=new Person1("张三");
var p2=new Person2("李四",18);
p1.hello();
p2.hello();
p2.me();
//第三种方法class类:es6
class Point{
//constructor方法会被自动调用
constructor(a,b){
console.log("构造函数被自动调用");
this.a=a;
this.b=b;
console.log("调用constructor:"+this.a+","+this.b);
}
fangfa1(){
console.log("调用fangfa1:"+this.a+","+this.b);
}
}
//声明的对象aa只会调用constructor()方法,因为这个方法是自动调用的
var aa=new Point(2,3);//构造函数被自动调用 调用constructor:2,3
console.log(typeof aa);//Object
/*声明的bb不知道为什么类型是undefined,想调用除constructor()以外的方法就要按照bb的句式写
但是这样写不仅会调用fangfa1(),还会自动调用constructor()*/
var bb=new Point(2,3).fangfa1();//构造函数被自动调用 调用constructor:2,3 调用fangfa1:2,3
console.log(typeof bb);//undefined
class Point2{
//constructor方法会被自动调用
constructor(a,b){
console.log("构造函数被自动调用");
this.a=a;
this.b=b;
console.log("调用constructor:"+this.a+","+this.b);
}
fangfa2(){
return "调用fangfa2:"+this.a+","+this.b;
}
fangfa3(){
return "你好,世界";
}
}
var cc=new Point2(5,5);
/*如果下面两句话同时出现,console.log(cc.fangfa2())打印的结果只是:调用fangfa2:5,5
但如果仅仅只是其中一句话出现,打印的结果就是这句话后面的注释部分*/
console.log(cc);//构造函数被自动调用 调用constructor:5,5 Point2 {a: 5, b: 5}
console.log(cc.fangfa2());//构造函数被自动调用 调用constructor:5,5 调用fangfa2:5,5
//class类里的方法名可以是一个变量,主要是为了用Symbol()类型的变量,防止重名
let aaa=Symbol();
class Point3{
//constructor方法会被自动调用
constructor(a,b){
console.log("构造函数被自动调用");
this.a=a;
this.b=b;
console.log("调用constructor:"+this.a+","+this.b);
}
fangfa2(){
return "调用fangfa2:"+this.a+","+this.b;
}
//把变量名放入方括号里
[aaa](){
return "你好,世界";
}
}
var dd=new Point3(3,3);
//如果变量是Symbol类型不能用点运算符,我最开始写成dd.aaa(),结果报错
console.log(dd[aaa]());
//class里的继承
class Parent{
//constructor方法会被自动调用
constructor(a,b){
console.log("构造函数被自动调用");
this.a=a;
this.b=b;
console.log("调用constructor:"+this.a+","+this.b);
}
fangfa2(){
return "调用fangfa2:"+this.a+","+this.b;
}
}
/*子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,
得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。*/
class Child extends Parent{
constructor(a,b,c){
super(a,b);//必须先用super关键字调用父类的方法
this.c=c;
}
fangfa3(){
return this.c+super.fangfa2();
}
}
//在子类传入新的参数后父类的参数值也被改变,意思是父类方法里打印的
//是子类的参数值
var ee=new Child("我是a","我是b","我是c");
console.log(ee.fangfa3())//我是c调用fangfa2:我是a,我是b
//php里的构造函数写法及调用
class Colors{
var $c1;
function __construct($c1="red"){
echo "自动调用函数";
$this->c1=$c1;
}
function c2(){
echo "方法二被调用";
return $this->c1;
}
}
$newcolor=new Colors("pink");
//php文件里调用除__construct以外的其他方法需要用"->"连接,
//php文件里调用属性也要用"->";
//注意千万不要用"."连接,会报错
echo $newcolor->c2();
?>
this的指向
1.在全局环境中,普通函数里的this指向的是顶层对象window(严格模式中,普通函数内部的this是undefined);
2.构造函数中this指的是实例对象;
3.如果对象的方法里包含this,this指向的就是方法运行时所在的对象
4.箭头函数中,this指向的是定义时所在的对象,而不是使用时所在的对象
封装函数里,如果想在方法里的事件内部调用这个方法外部的方法,可以在外部声明一个变量,var that=this;或者用bind绑定,又或者直接用箭头函数,因为箭头函数中,this指向的就是是定义时所在的对象,而不是使用时所在的对象-->
//1.全局环境 普通函数(严格模式中禁止this指向全局对象(window),避免无意间创造全局变量)
function fn(){
console.log(this);//返回的是window
}
fn();
function fn2(){
"use strict";//函数内部为严格模式
console.log(this);//返回的是undefined
}
fn2();
//2.构造函数
function Dog(p){
this.p=p;
console.log(this);//由于还没给p赋值,所以返回的是Dog {p: undefined}
}
var xiaohei=new Dog();
//3.对象 的方法
var obj={
fn3:function(){
console.log(this);//返回的是{fn3: ƒ}
}
}
obj.fn3();
//bink方法是将函数内的this绑定到指定的对象,然后返回新的对象
var dogs={
name:"小黑",
age:"1岁",
//在方法内部出现匿名函数,那么匿名函数里的this指向的对象是不确定的
voice:function(){
console.log(this.name);
setTimeout(function(){
console.log(this);//返回的是window
console.log(this.name);//没有返回值,因为这里的name是一个不存在的属性
//解决方法是console.log(dogs.name);
},1000);
}
}
dogs.voice();
//用bind绑定
/*在这个例子里新建的对象person1中一定要有一个属性名是say,并为它赋值,因为person中的方法act函数执行的是在后台打印this.say,要把person1用bind绑定给act,意思是act会从
对象person1中调用属性say, 如果没有这个属性say,就会打印出undefined,我第一次写的时候就犯了这样的错误,
在新建的对象中随便定义了一个属性名,却忘了act方法中执行的命令是指定要后台打印say属性的值*/
var person={
say:"你好",
act:function(){
console.log(this.say);
}
}
person.act();
var person1={say:"小萌"};
var aaa=person.act.bind(person1);
aaa();
Ps:程序员之路漫漫,持续不断的学习和复习方能使自己立于不败之地,翻身成码农之路不远了,决不能中途倒下,功亏一篑。
生活不止眼前的Bug,还有以后的Bug.....
来源:千锋HTML5