When you reference a property of an object (e.g. s1.arr), it first checks if the property exists on the object, if it does, it returns it, if it doesn't, it falls back to the object's prototype.
When you do s1.str += "1", which is equivalent to s1.str = s1.str + "1", you're setting the str property on the object itself, the prototype's str property doesn't change. s1.str will return the new string from s1, and s2.str will fall back to prototype.str.
s1's str s2's str prototype's str s1.str s2.str
before: - - "" "" (from proto) "" (from proto)
after: "1" "" "1" (from own) "" (from proto)
When you do s1.arr.push(1) you get s1.arr from the prototype, and you change its value. You never set the arr property on s1.
s1's arr s2's arr prototype's arr s1.arr s2.arr
before: - - [] [] (from proto) [] (from proto)
after: - - [1] [1] (from proto) [1] (from proto)